Vue混入mixins滾動觸底的方法
前言
在app端常??吹筋愃萍虞d數(shù)據(jù)的動畫,接下來我們來實現(xiàn)滾動觸底加載動畫提示,以及如何復用這些邏輯。

如何判斷滾動觸底
來看下幾張圖:
情況一:
當文檔高度還為超過可視區(qū)域高度時,不存在滾動,所以也沒有滾動觸底
情況二:
當文檔高度超過可視區(qū)域的高度時,還有剩余的文檔沒有滾動完,也就是說 可視區(qū)域高度 + 滾動高度 < 文檔高度 ,此時沒有達到滾動觸底的條件
情況三:
文檔高度大于可視區(qū)域,并且滾動到文檔底部, 也就是說 可視區(qū)域高度 + 滾動高度 = 文檔高度
判斷是否滾動到底
經(jīng)過上面三種情況的分析,我們需要拿到 可視區(qū)域的高度 , 滾動高度 , 文檔高度 這三個變量來進行比較。
可視區(qū)域的高度
function getWindowHeight() {
return document.documentElement.clientHeight;
}
滾動高度
對有doctype申明的頁面使用document.documentElement.scrollTop,safari特例獨行:使用 window.pageYOffset
function getScrollHeight() {
return Math.max(document.documentElement.scrollTop,window.pageYOffset||0)
}
文檔高度
function getDocumentTop() {
return document.documentElement.offsetHeight;
}
代碼實現(xiàn)
觸底打印
通過監(jiān)聽滾動事件來判斷 可視區(qū)域 , 滾動高度 , 文檔高度 的關系,實現(xiàn)最基礎的觸底加載
<div id="app">
<ul>
<li v-for="item in list" :key="item" > {{item}}</li>
</ul>
</div>
created(){
// 初始化數(shù)據(jù)
this.list = Array.from(Array(10),(item,index)=>index)
// 通過監(jiān)聽滾動事件來判斷 可視區(qū)域 , 滾動高度 ,文檔高度的關系
window.addEventListener('scroll',()=>{
let isBottom = (getScrollHeight() + getWindowHeight()) >= getDocumentTop()
if(isBottom){
console.log('觸底了',new Date())
let list = this.list
let last = list[list.length-1]
let newList = Array.from(Array(10),(item,index)=>index+last+1)
this.list.push(...newList)
}
})
}
優(yōu)化和復用滾動事件邏輯
將滾動邏輯抽取成 mixins 放在 scroll.js 中。優(yōu)化功能點如下:
- 增加觸底距離
- 滾動事件監(jiān)聽事件節(jié)流
- 添加觸底動畫,并將 UI 樣式一起封裝在 scroll.js 中
模擬請求事件
為了模擬請求數(shù)據(jù),封裝了一個 Promise 一秒后返回結(jié)果
methods:{
// 返回一個 promise ,用于請求服務端數(shù)據(jù)
findDataList(){
let list = this.list
let last = list[list.length-1]
return new Promise((resolve)=>{
// 模擬服務端數(shù)據(jù)
let newList = Array.from(Array(10),(item,index)=>index+last+1)
setTimeout(() => {
resolve(newList)
}, 1000);
})
}
}
滾動事件監(jiān)聽
滾動事件觸發(fā),判斷當前是否觸底,觸底了以后去執(zhí)行 loadMore 發(fā)起請求拿取服務端的數(shù)據(jù)
created(){
let fn = throttle(()=>{
let isOver = (getScrollHeight() + getWindowHeight()) >= (getDocumentTop()- MIN_INSTANCE)
// 觸底時進行數(shù)據(jù)加載
if(isOver){
// 創(chuàng)建加載組件
this.loadMore&&this.loadMore()
}
},DEALY_TIME)
window.addEventListener('scroll',fn)
},
添加觸底動畫
因為我們是將邏輯抽離在 mixins中,為了把觸底動畫也集成在里面使用 Vue.extend() 來實現(xiàn)編程式插入UI樣式的方法。
首先定義好 loading 組件的樣式
<template>
<div id="loading-alert">
<i class="el-icon-loading"></i>
<span>{{ message }}</span>
</div>
</template>
<script>
export default {
props:{
message:{
type:String,
default:'正在加載更多數(shù)據(jù)'
}
},
};
當觸底時去插入這個 loading 組件
import load from './load.vue'
data(){
return {
isLoading:false,
component:null
}
},
created(){
let fn = throttle(()=>{
let isOver = (getScrollHeight() + getWindowHeight()) >= (getDocumentTop()- MIN_INSTANCE)
// 觸底時進行l(wèi)oad組件顯示
if(isOver){
// 判斷l(xiāng)oading組件是否已經(jīng)存在,不存在就創(chuàng)建一個
if(!this.component){
this.component = extendComponents(load)
}
// 創(chuàng)建加載組件
this.loadMore&&this.loadMore()
// 判斷當前狀態(tài)來控制loading的組件顯示與否
if(!this.isLoading){
this.component.$el.remove()
// 將loading組件置為空
this.component = null
}
}
},DEALY_TIME)
window.addEventListener('scroll',fn)
},
詳細代碼
完整代碼可以 點擊查看 codepen 觸底動畫 關于上面代碼中 extendComponents 方法的實現(xiàn)可以查看詳細代碼,也可以查看 Vue.extend 編程式插入組件
最后
將滾動觸底的邏輯和 UI 都集成到 scroll.js 中,復用都方式可以放在 mixins 可以抽離成 v-directive,這樣我們可以接受到綁定的 dom 不僅僅可以做 window 的滾動觸底事件的判斷,也可以 實現(xiàn)單個元素的滾動事件觸底的監(jiān)聽 。后續(xù)可以在實現(xiàn) v-directive 的版本。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
vue用Object.defineProperty手寫一個簡單的雙向綁定的示例
這篇文章主要介紹了用Object.defineProperty手寫一個簡單的雙向綁定的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-07-07
前端使用vue實現(xiàn)token無感刷新的三種方案解析
這篇文章主要為大家介紹了前端使用vue實現(xiàn)token無感刷新的三種方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06
Vue.js每天必學之計算屬性computed與$watch
Vue.js每天必學之計算屬性computed與$watch,為大家詳細講解計算屬性computed與$watch,感興趣的小伙伴們可以參考一下2016-09-09

