JavaScript

超轻量级php框架startmvc

vue loadmore 组件滑动加载更多源码解析

更新时间:2020-05-25 12:30:01 作者:startmvc
上一篇讲到在项目中使用上拉加载更多组件,但是由于实际项目开发中由于需求变更或者说

上一篇讲到在项目中使用上拉加载更多组件,但是由于实际项目开发中由于需求变更或者说在webview中上拉加载有些机型在上拉时候会把webview也一起上拉导致上拉加载不灵敏等问题,我们有时候也会换成滑动到底部自动加载的功能。

既然都是加载更多,很多代码思想势必相似,主要区别在于上拉和滑动到底部这个操作上,所以,我们需要注意:

上拉加载是point指针touch触摸事件,现在因为是滑动加载,需要添加scroll事件去监听然后执行相应回调

上拉加载主要计算触摸滚动距离,滑动加载主要计算container底部和视窗上边缘的距离

事件绑定改成: 


 mounted() {
 ···
 this.dom.addEventListener('scroll', this.scroll, false)
 ···
 },
 beforeDestroy() {
 ···
 this.dom.removeEventListener('scroll', this.scroll, false)
 ···
 },

事件回调改为:


 /**
 * 滚动钩子
 */
 scroll() {
 const viewHeight = global.innerHeight
 let parentNode
 if (this.container !== global) {
 parentNode = this.$el
 } else {
 parentNode = this.$el.parentNode
 }
 if (parentNode) {
 // 获取Vue实例使用的根 DOM 元素相对于视口的位置
 const rect = parentNode.getBoundingClientRect()
 // this.distance 离底部多少距离开始加载
 // 如果此元素底边距离视口顶部的距离小于视口高度加上distance之和,就加载下一页
 if ((rect.bottom <= viewHeight + this.distance) && this.loadable && !this.loading) {
 this.load()
 }
 }
 },

源码如下:


<template>
 <div class="loadmore" ref="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>
<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,
 dom: null,
 }
 },
 props: {
 /**
 * 初始化后自动开始加载数据
 */
 autoload: {
 type: Boolean,
 default: true,
 },
 /**
 * 离组件最近的可滚动父级元素(用于监听事件及获取滚动条位置)
 */
 container: {
 // Selector or Element
 default: () => (global),
 },
 /**
 * 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: '',
 },
 /**
 * 距离底部多远加载
 */
 distance: {
 type: Number,
 default: 200,
 },
 },
 computed: {
 /**
 * 是否可以加载
 * @returns {boolean} 是与否
 */
 loadable() {
 return !this.started || (this.page + this.times) <= this.count
 },
 },
 mounted() {
 if (this.container !== global) {
 this.dom = document.querySelector(this.container)
 } else {
 this.dom = this.container
 }
 if (!this.dom) {
 return
 }
 this.dom.addEventListener('scroll', this.scroll, false)
 if (this.autoload && !this.loading) {
 this.load()
 }
 },
 // eslint-disable-next-line
 beforeDestroy() {
 if (this.dom) {
 this.dom.removeEventListener('scroll', this.scroll, false)
 }
 },
 methods: {
 /**
 * 滚动钩子
 */
 scroll() {
 const viewHeight = global.innerHeight
 let parentNode
 if (this.container !== global) {
 parentNode = this.$el
 } else {
 parentNode = this.$el.parentNode
 }
 if (parentNode) {
 const rect = parentNode.getBoundingClientRect()
 if ((rect.bottom <= viewHeight + this.distance) && this.loadable && !this.loading) {
 this.load()
 }
 }
 },
 /**
 * 加载一组数据的方法
 */
 load() {
 if (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()
 },
 },
 }
</script>

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

vue loadmore 滑动加载更多