基于VueJs加载更多控件实现

xiaoxiao2021-02-28  27

最近在研究vuejs上拉加载更多实现方案,上网找了下这方面的文章和代码貌似不是太多,而且逻辑实现并不太清晰,于是自己结合了前人的经验自己整合了下总结下经验. 上拉加载更多实现思路最关键的就是如何识别手指滑动操作,如果不是用vuejs,可以用html的onscroll函数来监听滑动的位置来实现,如果是基于vuejs,直接在标签里用onscroll事件是没用,这个具体没有研究清楚.下面就讲讲vuejs的方案,先贴出代码:

//scroll.vue <template lang="html"> <div class="yo-scroll" @touchstart="touchStart($event)" @touchmove="touchMove($event)" @touchend="touchEnd($event)" > <section class="inner"> <!-- 使用时外面的标签会填在里面 --> <slot> </slot> <!-- 保持加载更多条在最下面 --> <footer class="load-more"> <slot name="load-more"> <span>{{loadMoreText}}</span> </slot> </footer> <div class="nullData" v-show="dataList.noFlag">暂无更多数据</div> </section> </div> </template> <style lang="less"> /*:class="{'down':(state===0),'up':(state==1),refresh:(state===2),touch:touching}"*/ .yo-scroll { font-size: 24px; position: absolute; //关键 top: 0; right: 0; bottom: 0; left: 0; overflow: auto; //关键 z-index: 100; height: auto; -webkit-overflow-scrolling: touch; .inner { position: absolute; /*top: -5rem;*/ width: 100%; height: auto; transition-duration: 300ms; .load-more { height: 5rem; line-height: 5rem; display: flex; text-align: center; align-items: center; justify-content: center; display: none; } .nullData {//暂无更多数据样式 font-size: 26px; color: #999999; height: 100px; line-height: 100px; text-align: center; } .down-tip, .refresh-tip, .up-tip { display: none; } } } .yo-scroll.touch .inner { transition-duration: 0; } .yo-scroll.down .down-tip { display: block; } .yo-scroll.up .up-tip { display: block; } .yo-scroll.refresh .refresh-tip { display: block; } </style> <script> export default { props: { offset: { type: Number, default: 100 //默认高度 }, enableLoadMore: { type: Boolean, default: true }, dataList: { default: false, required: false }, onLoadMore: { type: Function, default: undefined, require: false } }, data() { return { startX: 0, startY: 0, touching: false, isLoading: false, loadMoreText: "上拉加载更多" } }, methods: { touchStart(e) { this.startY = e.targetTouches[0].pageY; this.startX = e.targetTouches[0].pageX; this.startScroll = this.$el.scrollTop || 0; this.touching = true; //留着有用,不能删除 this.dataList.noFlag = false; }, //滑动中 touchMove(e) { if(!this.enableLoadMore || this.dataList.noFlag || !this.touching) { return } let diff = e.targetTouches[0].pageY - this.startY - this.startScroll if(diff > 0) { e.preventDefault() } this.loadMoreText = '上拉加载更多' this.$el.querySelector('.load-more').style.display = 'block'; }, touchEnd(e) { if (this.isLoading) { return; } this.touching = false //用于判断滑动是否在原地 ----begin let endX = e.changedTouches[0].pageX, endY = e.changedTouches[0].pageY, dy = this.startY - endY, dx = endX - this.startX; //如果滑动距离太短 if(Math.abs(dx) < 2 && Math.abs(dy) < 2) { // console.log("滑动距离太短") let more = this.$el.querySelector('.load-more') more.style.display = 'none'; //隐藏加载条 return; } if(!this.enableLoadMore || this.isLoading) { let more = this.$el.querySelector('.load-more') more.style.display = 'none'; //隐藏加载条 return } let outerHeight = this.$el.clientHeight, innerHeight = this.$el.querySelector('.inner').clientHeight, scrollTop = this.$el.scrollTop, bottom = innerHeight - outerHeight - scrollTop; if(bottom <= this.offset) { //内容太少 this.doLoadMore(); } else { let more = this.$el.querySelector('.load-more') more.style.display = 'none'; //隐藏加载条 } }, doLoadMore() { this.isLoading = true this.loadMoreText = '正在加载' this.onLoadMore(this.loadDone); }, loadDone() { this.isLoading = false let more = this.$el.querySelector('.load-more') more.style.display = 'none'; //隐藏加载条 } } } </script>

这里是使用组件的方式实现, @touchstart=”touchStart( event)"@touchmove="touchMove( e v e n t ) " @ t o u c h m o v e =" t o u c h M o v e ( event)” @touchend=”touchEnd($event) 为布局加上滚动事件,具体实现在script里,touchStart先记录手指按下坐标,touchmove记录手指滑动的距离,判断是否显示更多条,touchEnd判断是否触发加载更多事件,一但达到条件就调用外面传进来的onLoadMore函数,通过外面的调用done来控制是否完成.实现的效果是上拉时显示”下拉加载更多”,手指释放时显示”正在加载”,完成后隐藏控制条. 外面使用的组件代码 :

<template> <div> <v-scroll :onLoadMore="onLoadMore" :dataList="scrollData"> <ul> <li v-for="(item) in listdata" :key="item.name">{{item.name}}</li> <li v-for="(item) in downdata" :key="item.name">{{item.name}}</li> </ul> </v-scroll> </div> </template> <style lang="less"> ul li { min-height: 100px; line-height: 100px; text-align: center; border: 1px solid red; } </style> <script> import loadmore from "./scroll.vue"; export default { components: { 'v-scroll': loadmore }, data() { return { counter: 1, //当前页 num: 10, // 一页显示多少条 pageStart: 0, // 开始页数 pageEnd: 0, // 结束页数 listdata: [], // 下拉更新数据存放数组 downdata: [], // 上拉更多的数据存放数组 scrollData:{ noFlag: false //暂无更多数据显示 } } }, mounted: function() { this.getList(); }, methods: { getList() { var response = [] for(let i = 0; i < 60; i++) { response.push({ name: i }) } this.listdata = response.slice(0, this.num); }, onLoadMore(done) { this.counter++; let end = this.pageEnd = this.num * this.counter; let i = this.pageStart = this.pageEnd - this.num; setTimeout(() => { for(i; i < end; i++) { if(i >= 30) { //走完数据调用方法 // this.scrollData.noFlag = true; break; } else { this.downdata.push({ name: i + "===" }) // more.style.display = 'none'; //隐藏加载条 } } done(); }, 2000); } } } </script>

实现的完整代码在github上可以找到:https://github.com/Cmdmac/vuejs-loadmore.git

转载请注明原文地址: https://www.6miu.com/read-2599949.html

最新回复(0)