我是靠谱客的博主 娇气小天鹅,这篇文章主要介绍vue loadmore组件上拉加载更多功能示例代码,现在分享给大家,希望可以做个参考。

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

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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生命周期来挂载事件和销毁事件

复制代码
1
2
3
4
5
6
7
8
9
export default { mounted() { // 确定容器 // 容器绑定事件 }, beforeDestory() { // 解绑事件 }, }

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

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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传入或者一些逻辑控制细节需要再额外添加,贴出整个组件的源码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
<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>

以上所述是小编给大家介绍的vue loadmore组件上拉加载更多功能示例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

最后

以上就是娇气小天鹅最近收集整理的关于vue loadmore组件上拉加载更多功能示例代码的全部内容,更多相关vue内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(116)

评论列表共有 0 条评论

立即
投稿
返回
顶部