vue瀑布流组件实现上拉加载更多
网络编程 2021-07-04 15:02www.168986.cn编程入门
这篇文章主要为大家详细介绍了vue瀑布流组件实现上拉加载更多,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
最近在做移动端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 ? e.changedTouches[0].pageY : e.pageY }, / 鼠标移动事件处理函数 @param {Object} e - 事件对象 / pointermove(e) { 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 }, }, ··· }
基本上主干已经算完工了,一些props传入或者一些逻辑控制细节需要再额外添加,贴出整个组件的源码
<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./mzabriskie/axios#request-config} / options: { type: Object, default: null, }, / 起始页码 / page: { type: Number, default: 1, }, / 每页加载数据条数 / rows: { type: Number, default: 10, }, / 数据加载请求地址 / url: { type: String, default: '', }, }, puted: { / 是否可以加载 @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('suess', data.list) this.$emit('plete') }).catch((e) => { this.loading = false this.$emit('error', e) this.$emit('plete') }) }, / 重置加载相关变量 / 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>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持狼蚁SEO。
上一篇:vue中的使用token的方法示例
下一篇:JS如何在数组指定位置插入元素
编程语言
- 如何快速学会编程 如何快速学会ug编程
- 免费学编程的app 推荐12个免费学编程的好网站
- 电脑怎么编程:电脑怎么编程网咯游戏菜单图标
- 如何写代码新手教学 如何写代码新手教学手机
- 基础编程入门教程视频 基础编程入门教程视频华
- 编程演示:编程演示浦丰投针过程
- 乐高编程加盟 乐高积木编程加盟
- 跟我学plc编程 plc编程自学入门视频教程
- ug编程成航林总 ug编程实战视频
- 孩子学编程的好处和坏处
- 初学者学编程该从哪里开始 新手学编程从哪里入
- 慢走丝编程 慢走丝编程难学吗
- 国内十强少儿编程机构 中国少儿编程机构十强有
- 成人计算机速成培训班 成人计算机速成培训班办
- 孩子学编程网上课程哪家好 儿童学编程比较好的
- 代码编程教学入门软件 代码编程教程