本文實例為大家分享了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; }, }
這樣就完成了。
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com