vue loadmore 組件滑動(dòng)加載更多源碼解析
上一篇講到在項(xiàng)目中使用上拉加載更多組件,但是由于實(shí)際項(xiàng)目開發(fā)中由于需求變更或者說(shuō)在webview中上拉加載有些機(jī)型在上拉時(shí)候會(huì)把webview也一起上拉導(dǎo)致上拉加載不靈敏等問題,我們有時(shí)候也會(huì)換成滑動(dòng)到底部自動(dòng)加載的功能。
既然都是加載更多,很多代碼思想勢(shì)必相似,主要區(qū)別在于上拉和滑動(dòng)到底部這個(gè)操作上,所以,我們需要注意:
上拉加載是point指針touch觸摸事件,現(xiàn)在因?yàn)槭腔瑒?dòng)加載,需要添加scroll事件去監(jiān)聽然后執(zhí)行相應(yīng)回調(diào)
上拉加載主要計(jì)算觸摸滾動(dòng)距離,滑動(dòng)加載主要計(jì)算container底部和視窗上邊緣的距離
事件綁定改成:
mounted() {
···
this.dom.addEventListener('scroll', this.scroll, false)
···
},
beforeDestroy() {
···
this.dom.removeEventListener('scroll', this.scroll, false)
···
},
事件回調(diào)改為:
/**
* 滾動(dòng)鉤子
*/
scroll() {
const viewHeight = global.innerHeight
let parentNode
if (this.container !== global) {
parentNode = this.$el
} else {
parentNode = this.$el.parentNode
}
if (parentNode) {
// 獲取Vue實(shí)例使用的根 DOM 元素相對(duì)于視口的位置
const rect = parentNode.getBoundingClientRect()
// this.distance 離底部多少距離開始加載
// 如果此元素底邊距離視口頂部的距離小于視口高度加上distance之和,就加載下一頁(yè)
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 {
/**
* 總頁(yè)數(shù)(由服務(wù)端返回)
* @type {number}
*/
count: 0,
/**
* 是否正在拖拽中
* @type {boolean}
*/
dragging: false,
/**
* 已加載次數(shù)
* @type {number}
*/
times: 0,
/**
* 已開始記載
* @type {boolean}
*/
started: false,
/**
* 正在加載中
* @type {boolean}
*/
loading: false,
dom: null,
}
},
props: {
/**
* 初始化后自動(dòng)開始加載數(shù)據(jù)
*/
autoload: {
type: Boolean,
default: true,
},
/**
* 離組件最近的可滾動(dòng)父級(jí)元素(用于監(jiān)聽事件及獲取滾動(dòng)條位置)
*/
container: {
// Selector or Element
default: () => (global),
},
/**
* Axios請(qǐng)求參數(shù)配置對(duì)象
* {@link https://github.com/mzabriskie/axios#request-config}
*/
options: {
type: Object,
default: null,
},
/**
* 起始頁(yè)碼
*/
page: {
type: Number,
default: 1,
},
/**
* 每頁(yè)加載數(shù)據(jù)條數(shù)
*/
rows: {
type: Number,
default: 10,
},
/**
* 數(shù)據(jù)加載請(qǐng)求地址
*/
url: {
type: String,
default: '',
},
/**
* 距離底部多遠(yuǎn)加載
*/
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: {
/**
* 滾動(dòng)鉤子
*/
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()
}
}
},
/**
* 加載一組數(shù)據(jù)的方法
*/
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')
})
},
/**
* 重置加載相關(guān)變量
*/
reset() {
this.count = 0
this.times = 0
this.started = false
this.loading = false
},
/**
*重新開始加載
*/
restart() {
this.reset()
this.load()
},
},
}
</script>
以上所述是小編給大家介紹的vue loadmore 組件滑動(dòng)加載更多源碼解析,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- 基于Vue實(shí)現(xiàn)頁(yè)面切換左右滑動(dòng)效果
- Vue實(shí)現(xiàn)移動(dòng)端左右滑動(dòng)效果的方法
- vue實(shí)現(xiàn)一個(gè)移動(dòng)端屏蔽滑動(dòng)的遮罩層實(shí)例
- vue2.0移動(dòng)端滑動(dòng)事件vue-touch的實(shí)例代碼
- vue中選項(xiàng)卡點(diǎn)擊切換且能滑動(dòng)切換功能的實(shí)現(xiàn)代碼
- vue-router 手勢(shì)滑動(dòng)觸發(fā)返回功能
- vue-awesome-swiper 基于vue實(shí)現(xiàn)h5滑動(dòng)翻頁(yè)效果【推薦】
- 使用Vue 實(shí)現(xiàn)滑動(dòng)驗(yàn)證碼功能
- Vue實(shí)現(xiàn)固定定位圖標(biāo)滑動(dòng)隱藏效果
- 使用vue制作滑動(dòng)標(biāo)簽
- Vue 實(shí)現(xiàn)從小到大的橫向滑動(dòng)效果詳解
相關(guān)文章
VueJs中的shallowRef與shallowReactive函數(shù)使用比較
這篇文章主要為大家介紹了VueJs中的shallowRef與shallowReactive函數(shù)的使用比較解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
vue+elementUI實(shí)現(xiàn)圖片上傳功能
這篇文章主要為大家詳細(xì)介紹了vue+elementUI實(shí)現(xiàn)圖片上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08
vue用vis插件如何實(shí)現(xiàn)網(wǎng)絡(luò)拓?fù)鋱D
這篇文章主要介紹了vue用vis插件如何實(shí)現(xiàn)網(wǎng)絡(luò)拓?fù)鋱D,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
通過(guò)debug搞清楚.vue文件如何變成.js文件(案例詳解)
這篇文章主要介紹了通過(guò)debug搞清楚.vue文件如何變成.js文件,本文以@vitejs/plugin-vue舉例,通過(guò)debug的方式帶你一步一步的搞清楚vue文件是如何編譯為js文件的,需要的朋友可以參考下2024-07-07
Vue項(xiàng)目中數(shù)據(jù)的深度監(jiān)聽或?qū)ο髮傩缘谋O(jiān)聽實(shí)例
這篇文章主要介紹了Vue項(xiàng)目中數(shù)據(jù)的深度監(jiān)聽或?qū)ο髮傩缘谋O(jiān)聽實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
Vue生命周期activated之返回上一頁(yè)不重新請(qǐng)求數(shù)據(jù)操作
這篇文章主要介紹了Vue生命周期activated之返回上一頁(yè)不重新請(qǐng)求數(shù)據(jù)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
Vue.js仿Metronic高級(jí)表格(一)靜態(tài)設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了Vue.js仿Metronic高級(jí)表格的靜態(tài)設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04

