基于vue2實現(xiàn)上拉加載功能
本文實例為大家分享了vue2實現(xiàn)上拉加載展示的具體代碼,供大家參考,具體內(nèi)容如下
因為我們項目中,還用了swiper。很多都是滑動切換的,但是又得上拉加載,所以導致,很多UI框架,我們用了,都有不同的bug出現(xiàn),沒辦法,最后寫了一個。代碼如下(這個因為很多地方會用,所以建議放在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 {
// 最下面出現(xiàn)的div的位移
translate: 0,
// 選擇滾動事件的監(jiān)聽對象
scrollEventTarget: null,
containerFilled: false,
bottomText: '',
// class類名
bottomDropped: false,
// 獲取監(jiān)聽滾動元素的scrollTop
bottomReached: false,
// 滑動的方向 down---向下互動;up---向上滑動
direction: '',
startY: 0,
startScrollTop: 0,
// 實時的clientY位置
currentY: 0,
topStatus: '',
// 上拉加載的狀態(tài) '' pull: 上拉中
bottomStatus: '',
};
},
watch: {
// 改變當前加載在狀態(tài)
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';
// 選擇滾動事件的監(jiān)聽對象
this.scrollEventTarget = this.getScrollEventTarget(this.$el);
if (typeof this.bottomMethod === 'function') {
// autoFill 屬性的實現(xiàn) 注釋
this.fillContainer();
// 綁定滑動事件
this.bindTouchEvents();
}
},
// autoFill 屬性的實現(xiàn) 注釋
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();
}
});
}
},
// 獲取監(jiān)聽滾動元素的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) {
// 沒有在需要滾動的范圍內(nèi)滾動,不再監(jiān)聽scroll
return;
}
// 實時的clientY位置
this.currentY = event.touches[0].clientY;
// distance 移動位置和開始位置的差值 distanceIndex---
let distance = (this.currentY - this.startY) / this.distanceIndex;
// 根據(jù) distance 判斷滑動的方向 并賦予變量 direction down---向下互動;up---向上滑動
this.direction = distance > 0 ? 'down' : 'up';
if (this.direction === 'up') {
// 獲取監(jiān)聽滾動元素的scrollTop
this.bottomReached = this.bottomReached || this.checkBottomReached();
}
if (typeof this.bottomMethod === 'function' && this.direction === 'up' &&
this.bottomReached && this.bottomStatus !== 'loading' && !this.bottomAllLoaded) {
// 有加載函數(shù),是向上拉,有滾動距離,不是正在加載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 {
// 上拉加載數(shù)據(jù)
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; // 每次更迭加載的頁數(shù)
if (this.pageNo == this.totalGetCount) {
// 當allLoaded = true時上拉加載停止
this.loading = false;
this.allLoaded = true;
}
api.commonApi(后臺接口,請求參數(shù)) 這個api是封裝的axios有不懂的可以看vue2+vuex+axios那篇文章
.then(res => {
setTimeout(() => {
要使用的后臺返回的數(shù)據(jù)寫在setTimeout里面
this.$nextTick(() => {
this.loading = false;
})
}, 1000)
});
},
handleBottomChange(status) {
this.bottomStatus = status;
},
}
這樣就完成了。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
把vue-router和express項目部署到服務器的方法
下面小編就為大家分享一篇把vue-router和express項目部署到服務器的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-02-02
element-plus日歷(Calendar)動態(tài)渲染以及避坑指南
這篇文章主要給大家介紹了關于element-plus日歷(Calendar)動態(tài)渲染以及避坑指南的相關資料,這是最近幫一個后端朋友處理一個前端問題,elementUI中calendar日歷組件內(nèi)容進行自定義顯示,實現(xiàn)類似通知事項的日歷效果,需要的朋友可以參考下2023-08-08
VueJs使用Amaze ui調(diào)整列表和內(nèi)容頁面
這篇文章主要介紹了VueJs 填坑日記之使用Amaze ui調(diào)整列表和內(nèi)容頁面,需要的朋友可以參考下2017-11-11
ElementUI組件Dialog彈窗再次打開表單仍顯示上次數(shù)據(jù)的問題
這篇文章主要介紹了ElementUI組件Dialog彈窗再次打開表單仍顯示上次數(shù)據(jù)的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04
尤雨溪開發(fā)vue?dev?server理解vite原理
這篇文章主要為大家介紹了尤雨溪開發(fā)的玩具vite,vue-dev-server來理解vite原理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07
vue結(jié)合v-for和input實現(xiàn)多選列表checkbox功能
在Vue中,可通過v-for指令和v-model實現(xiàn)多選列表功能,首先,使用v-for指令遍歷數(shù)組生成列表項,每個列表項包含一個復選框,復選框的v-model綁定到一個數(shù)組變量,用于存儲選中的值,感興趣的朋友跟隨小編一起看看吧2024-09-09
解決vue動態(tài)為數(shù)據(jù)添加新屬性遇到的問題
今天小編就為大家分享一篇解決vue動態(tài)為數(shù)據(jù)添加新屬性遇到的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09

