DDR爱好者之家 Design By 杰米

最近在做移动端h5页面,所以分页什么的就不能按照传统pc端的分页器的思维去做了,这么小的屏幕去点击也不太方便一般来讲移动端都是上拉加载更多,符合正常使用习惯。

首先简单写一下模板部分的html代码,,很简单清晰的逻辑:

<template>
 <div class="loadmore">
 <div class="loadmore__body">
  <slot></slot>
 </div>
 <div class="loadmore__footer">
  <span v-if="loading">
  <i class="tc-loading"></i>
  <span>正在加载</span>
  </span>
  <span v-else-if="loadable">上拉加载更多</span>
  <span v-else>没有更多了</span>
 </div>
 </div>
</template>

然后就是业务部分了

在动手写组件之前,先理清需求:

加载页面 -> 滑到底部 -> 上拉一定距离 -> 加载第二页 -> 继续前面步骤 -> 没有更多

这是一个用户交互逻辑,而我们需要将其映射为代码逻辑:

首屏自动加载第一页 -> 滑动到底部&&按下时候滑动距离Y轴有一定偏移量 -> 请求后端加载第二页 -> 根据返回字段判断是否还有下一页

有了代码逻辑,主干就出来了,加载和判断由事件来控制,而又作为一个vue组件,我们需要配合vue生命周期来挂载事件和销毁事件

export default {
 mounted() {
  // 确定容器
  // 容器绑定事件
 },
 beforeDestory() {
  // 解绑事件
 },
}

如果没有解绑的话,每次你加载组件,就会绑定一次事件…

然后我们需要一些核心事件回调方法来在合适的时间加载数据渲染页面, 回想一下,第一我们需要http获取数据的load函数,然后我们需要三个绑定事件的回调函数pointDown(), pointMove(), pointUp(),分别对应用户按下、移动、弹起手指操作:

export default {
 ···
 methods:{
  /**
  * 加载一组数据的方法
  */
  load() {
   // 设置options
  this.$axios.request(options).then((res) => {
   // 获取数据后的处理
  }).catch((e) => {
   // 异常处理
  })
  },
  /**
  * 鼠标按下事件处理函数
  * @param {Object} e - 事件对象
  */
  pointerdown(e) {
  // 获取按下的位置
  this.pageY = e.changedTouches "htmlcode">
<template>
 <div class="loadmore">
 <!-- <div class="loadmore__header"></div> -->
 <div class="loadmore__body">
  <slot></slot>
 </div>
 <div class="loadmore__footer">
  <span v-if="loading">
  <i class="tc-loading"></i>
  <span>正在加载</span>
  </span>
  <span v-else-if="loadable">上拉加载更多</span>
  <span v-else>没有更多了</span>
 </div>
 </div>
</template>

<script type="text/babel">
 import axios from 'axios'

 const CancelToken = axios.CancelToken

 export default {
 data() {
  return {
  /**
   * 总页数(由服务端返回)
   * @type {number}
   */
  count: 0,

  /**
   * 是否正在拖拽中
   * @type {boolean}
   */
  dragging: false,

  /**
   * 已加载次数
   * @type {number}
   */
  times: 0,

  /**
   * 已开始记载
   * @type {boolean}
   */
  started: false,

  /**
   * 正在加载中
   * @type {boolean}
   */
  loading: false,
  }
 },

 props: {
  /**
  * 初始化后自动开始加载数据
  */
  autoload: {
  type: Boolean,
  default: true,
  },

  /**
  * 离组件最近的可滚动父级元素(用于监听事件及获取滚动条位置)
  */
  container: {
  // Selector or Element
  default: 'body',
  },

  /**
  * 禁用组件
  */
  disabled: {
  type: Boolean,
  default: false,
  },

  /**
  * Axios请求参数配置对象
  * {@link https://github.com/mzabriskie/axios#request-config}
  */
  options: {
  type: Object,
  default: null,
  },

  /**
  * 起始页码
  */
  page: {
  type: Number,
  default: 1,
  },

  /**
  * 每页加载数据条数
  */
  rows: {
  type: Number,
  default: 10,
  },

  /**
  * 数据加载请求地址
  */
  url: {
  type: String,
  default: '',
  },
 },

 computed: {
  /**
  * 是否可以加载
  * @returns {boolean} 是与否
  */
  loadable() {
  return !this.disabled && (!this.started || (this.page + this.times) <= this.count)
  },
 },

 mounted() {
  let container = this.container

  if (container) {
  if (typeof container === 'string') {
   container = document.querySelector(container)
  } else if (!container.querySelector) {
   container = document.body
  }
  }

  if (!container) {
  container = document.body
  }

  this.$container = container
  this.onPointerDown = this.pointerdown.bind(this)
  this.onPointerMove = this.pointermove.bind(this)
  this.onPointerUp = this.pointerup.bind(this)

  if (global.PointerEvent) {
  container.addEventListener('pointerdown', this.onPointerDown, false)
  container.addEventListener('pointermove', this.onPointerMove, false)
  container.addEventListener('pointerup', this.onPointerUp, false)
  container.addEventListener('pointercancel', this.onPointerUp, false)
  } else {
  container.addEventListener('touchstart', this.onPointerDown, false)
  container.addEventListener('touchmove', this.onPointerMove, false)
  container.addEventListener('touchend', this.onPointerUp, false)
  container.addEventListener('touchcancel', this.onPointerUp, false)
  container.addEventListener('mousedown', this.onPointerDown, false)
  container.addEventListener('mousemove', this.onPointerMove, false)
  container.addEventListener('mouseup', this.onPointerUp, false)
  }

  if (this.autoload) {
  this.load()
  }
 },

 // eslint-disable-next-line
 beforeDestroy() {
  const container = this.$container

  if (global.PointerEvent) {
  container.removeEventListener('pointerdown', this.onPointerDown, false)
  container.removeEventListener('pointermove', this.onPointerMove, false)
  container.removeEventListener('pointerup', this.onPointerUp, false)
  container.removeEventListener('pointercancel', this.onPointerUp, false)
  } else {
  container.removeEventListener('touchstart', this.onPointerDown, false)
  container.removeEventListener('touchmove', this.onPointerMove, false)
  container.removeEventListener('touchend', this.onPointerUp, false)
  container.removeEventListener('touchcancel', this.onPointerUp, false)
  container.removeEventListener('mousedown', this.onPointerDown, false)
  container.removeEventListener('mousemove', this.onPointerMove, false)
  container.removeEventListener('mouseup', this.onPointerUp, false)
  }

  if (this.loading && this.cancel) {
  this.cancel()
  }
 },

 methods: {
  /**
  * 加载一组数据的方法
  */
  load() {
  if (this.disabled || this.loading) {
   return
  }

  this.started = true
  this.loading = true

  const params = {
   currentPage: this.page + this.times,
   pageSize: this.rows,
  }
  const options = Object.assign({}, this.options, {
   url: this.url,
   cancelToken: new CancelToken((cancel) => {
   this.cancel = cancel
   }),
  })

  if (String(options.method).toUpperCase() === 'POST') {
   options.data = Object.assign({}, options.data, params)
  } else {
   options.params = Object.assign({}, options.params, params)
  }

  this.$axios.request(options).then((res) => {
   const data = res.result

   this.times += 1
   this.loading = false
   this.count = data.pageCount
   this.$emit('success', data.list)
   this.$emit('complete')
  }).catch((e) => {
   this.loading = false
   this.$emit('error', e)
   this.$emit('complete')
  })
  },

  /**
  * 重置加载相关变量
  */
  reset() {
  this.count = 0
  this.times = 0
  this.started = false
  this.loading = false
  },

  /**
  *重新开始加载
  */
  restart() {
  this.reset()
  this.load()
  },

  /**
  * 鼠标按下事件处理函数
  * @param {Object} e - 事件对象
  */
  pointerdown(e) {
  if (this.disabled || !this.loadable || this.loading) {
   return
  }

  this.dragging = true
  this.pageY = e.changedTouches ? e.changedTouches[0].pageY : e.pageY
  },

  /**
  * 鼠标移动事件处理函数
  * @param {Object} e - 事件对象
  */
  pointermove(e) {
  if (!this.dragging) {
   return
  }

  const container = this.$container
  const pageY = e.changedTouches ? e.changedTouches[0].pageY : e.pageY
  const moveY = pageY - this.pageY

  // 如果已经向下滚动到页面最底部
  if (moveY < 0 && (container.scrollTop + Math.min(
   global.innerHeight,
   container.clientHeight,
  )) >= container.scrollHeight) {
   // 阻止原生的上拉拖动会露出页面底部空白区域的行为(主要针对iOS版微信)
   e.preventDefault()

   // 如果上拉距离超过50像素,则加载下一页
   if (moveY < -50) {
   this.pageY = pageY
   this.load()
   }
  }
  },

  /**
  * 鼠标松开事件处理函数
  */
  pointerup() {
  this.dragging = false
  },
 },
 }
</script>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

DDR爱好者之家 Design By 杰米
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
DDR爱好者之家 Design By 杰米

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。