基于vue2实现上拉加载功能
程序员文章站
2022-06-25 13:23:05
本文实例为大家分享了vue2实现上拉加载展示的具体代码,供大家参考,具体内容如下
因为我们项目中,还用了swiper。很多都是滑动切换的,但是又得上拉加载,所以导致,很多...
本文实例为大家分享了vue2实现上拉加载展示的具体代码,供大家参考,具体内容如下
因为我们项目中,还用了swiper。很多都是滑动切换的,但是又得上拉加载,所以导致,很多ui框架,我们用了,都有不同的bug出现,没办法,最后写了一个。代码如下(这个因为很多地方会用,所以建议放在components/common下面):
<template> <div class="loadmore"> <slot></slot> <slot name="bottom"> </slot> </div> </template> <style> .loadmore{ width:100%; } </style> <script> export default { name: 'loadmore', props: { maxdistance: { type: number, default: 0 }, autofill: { type: boolean, default: true }, distanceindex: { type: number, default: 2 }, bottompulltext: { type: string, default: '上拉刷新' }, bottomdroptext: { type: string, default: '释放更新' }, bottomloadingtext: { type: string, default: '加载中...' }, bottomdistance: { type: number, default: 70 }, bottommethod: { type: function }, bottomallloaded: { type: boolean, default: false }, }, data() { return { // 最下面出现的div的位移 translate: 0, // 选择滚动事件的监听对象 scrolleventtarget: null, containerfilled: false, bottomtext: '', // class类名 bottomdropped: false, // 获取监听滚动元素的scrolltop bottomreached: false, // 滑动的方向 down---向下互动;up---向上滑动 direction: '', starty: 0, startscrolltop: 0, // 实时的clienty位置 currenty: 0, topstatus: '', // 上拉加载的状态 '' pull: 上拉中 bottomstatus: '', }; }, watch: { // 改变当前加载在状态 bottomstatus(val) { this.$emit('bottom-status-change', val); switch (val) { case 'pull': this.bottomtext = this.bottompulltext; break; case 'drop': this.bottomtext = this.bottomdroptext; break; case 'loading': this.bottomtext = this.bottomloadingtext; break; } } }, methods: { onbottomloaded() { this.bottomstatus = 'pull'; this.bottomdropped = false; this.$nexttick(() => { if (this.scrolleventtarget === window) { document.body.scrolltop += 50; } else { this.scrolleventtarget.scrolltop += 50; } this.translate = 0; }); // 注释 if (!this.bottomallloaded && !this.containerfilled) { this.fillcontainer(); } }, getscrolleventtarget(element) { let currentnode = element; while (currentnode && currentnode.tagname !== 'html' && currentnode.tagname !== 'body' && currentnode.nodetype === 1) { let overflowy = document.defaultview.getcomputedstyle(currentnode).overflowy; if (overflowy === 'scroll' || overflowy === 'auto') { return currentnode; } currentnode = currentnode.parentnode; } return window; }, // 获取scrolltop getscrolltop(element) { if (element === window) { return math.max(window.pageyoffset || 0, document.documentelement.scrolltop); } else { return element.scrolltop; } }, bindtouchevents() { this.$el.addeventlistener('touchstart', this.handletouchstart); this.$el.addeventlistener('touchmove', this.handletouchmove); this.$el.addeventlistener('touchend', this.handletouchend); }, init() { this.bottomstatus = 'pull'; // 选择滚动事件的监听对象 this.scrolleventtarget = this.getscrolleventtarget(this.$el); if (typeof this.bottommethod === 'function') { // autofill 属性的实现 注释 this.fillcontainer(); // 绑定滑动事件 this.bindtouchevents(); } }, // autofill 属性的实现 注释 fillcontainer() { if (this.autofill) { this.$nexttick(() => { if (this.scrolleventtarget === window) { this.containerfilled = this.$el.getboundingclientrect().bottom >= document.documentelement.getboundingclientrect().bottom; } else { this.containerfilled = this.$el.getboundingclientrect().bottom >= this.scrolleventtarget.getboundingclientrect().bottom; } if (!this.containerfilled) { this.bottomstatus = 'loading'; this.bottommethod(); } }); } }, // 获取监听滚动元素的scrolltop checkbottomreached() { if (this.scrolleventtarget === window) { return document.body.scrolltop + document.documentelement.clientheight >= document.body.scrollheight; } else { // getboundingclientrect用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。 right是指元素右边界距窗口最左边的距离,bottom是指元素下边界距窗口最上面的距离。 return this.$el.getboundingclientrect().bottom <= this.scrolleventtarget.getboundingclientrect().bottom + 1; } }, // ontouchstart 事件 handletouchstart(event) { // 获取起点的y坐标 this.starty = event.touches[0].clienty; this.startscrolltop = this.getscrolltop(this.scrolleventtarget); this.bottomreached = false; if (this.bottomstatus !== 'loading') { this.bottomstatus = 'pull'; this.bottomdropped = false; } }, // ontouchmove事件 handletouchmove(event) { if (this.starty < this.$el.getboundingclientrect().top && this.starty > this.$el.getboundingclientrect().bottom) { // 没有在需要滚动的范围内滚动,不再监听scroll return; } // 实时的clienty位置 this.currenty = event.touches[0].clienty; // distance 移动位置和开始位置的差值 distanceindex--- let distance = (this.currenty - this.starty) / this.distanceindex; // 根据 distance 判断滑动的方向 并赋予变量 direction down---向下互动;up---向上滑动 this.direction = distance > 0 ? 'down' : 'up'; if (this.direction === 'up') { // 获取监听滚动元素的scrolltop this.bottomreached = this.bottomreached || this.checkbottomreached(); } if (typeof this.bottommethod === 'function' && this.direction === 'up' && this.bottomreached && this.bottomstatus !== 'loading' && !this.bottomallloaded) { // 有加载函数,是向上拉,有滚动距离,不是正在加载ajax,没有加载到最后一页 event.preventdefault(); event.stoppropagation(); if (this.maxdistance > 0) { this.translate = math.abs(distance) <= this.maxdistance ? this.getscrolltop(this.scrolleventtarget) - this.startscrolltop + distance : this.translate; } else { this.translate = this.getscrolltop(this.scrolleventtarget) - this.startscrolltop + distance; } if (this.translate > 0) { this.translate = 0; } this.bottomstatus = -this.translate >= this.bottomdistance ? 'drop' : 'pull'; } }, // ontouchend事件 handletouchend() { if (this.direction === 'up' && this.bottomreached && this.translate < 0) { this.bottomdropped = true; this.bottomreached = false; if (this.bottomstatus === 'drop') { this.translate = '-50'; this.bottomstatus = 'loading'; this.bottommethod(); } else { this.translate = '0'; this.bottomstatus = 'pull'; } } this.direction = ''; } }, mounted() { this.init(); } }; </script>
然后哪个页面需要,在哪个页面导入即可:import loadmore from './../common/loadmore.vue';在需要引入他的页面写法如下:
<template> <section class="finan"> <!-- 上拉加载更多 --> <load-more :bottom-method="loadbottom" :bottom-all-loaded="allloaded" :bottompulltext='bottomtext' :auto-fill="false" @bottom-status-change="handlebottomchange" ref="loadmore"> <div> 这里写你需要的另外的模块 </div> <div v-show="loading" slot="bottom" class="loading"> 这个div是为让上拉加载的时候显示一张加载的gif图 <img src="./../../assets/main/uploading.gif"> </div> </load-more> </section> </template>
然后在此页面的data里和methods设置如下:
export default { name: 'financialgroup', props:{ }, data () { return { // 上拉加载数据 scrollheight: 0, scrolltop: 0, containerheight: 0, loading: false, allloaded: false, bottomtext: '上拉加载更多...', bottomstatus: '', pageno: 1, totalcount: '', } }, methods: { /* 下拉加载 */ _scroll: function(ev) { ev = ev || event; this.scrollheight = this.$refs.innerscroll.scrollheight; this.scrolltop = this.$refs.innerscroll.scrolltop; this.containerheight = this.$refs.innerscroll.offsetheight; }, loadbottom: function() { this.loading = true; this.pageno += 1; // 每次更迭加载的页数 if (this.pageno == this.totalgetcount) { // 当allloaded = true时上拉加载停止 this.loading = false; this.allloaded = true; } api.commonapi(后台接口,请求参数) 这个api是封装的axios有不懂的可以看vue2+vuex+axios那篇文章 .then(res => { settimeout(() => { 要使用的后台返回的数据写在settimeout里面 this.$nexttick(() => { this.loading = false; }) }, 1000) }); }, handlebottomchange(status) { this.bottomstatus = status; }, }
这样就完成了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: JavaScript的setter与getter方法
下一篇: 微信小程序用户自定义模版用法实例分析