手寫vue無限滾動(dòng)指令的詳細(xì)過程
概述
日常的開發(fā)當(dāng)中,為了處理大量數(shù)據(jù)的情況,一般前端會(huì)采用分頁展示,可以通過分頁插件進(jìn)行數(shù)據(jù)的按需分頁請(qǐng)求展示,另一種解決大量數(shù)據(jù)的渲染的方式就是無限滾動(dòng),在移動(dòng)端比較常見,也就是我們常見的滾動(dòng)到底部加載更多數(shù)據(jù),一般web端用下拉加載更多場景不是很多,但是也還是有,比如京東和淘寶的web官方,就用到了無限滾動(dòng),通過滾動(dòng)到底部,然后加載更多數(shù)據(jù)??傊?,無限滾動(dòng)和分頁插件都是為了解決大數(shù)據(jù)展示的問題,現(xiàn)在介紹下vue中通過自定義指令實(shí)現(xiàn)無限滾動(dòng)。
最終效果
實(shí)現(xiàn)原理
在開始敲代碼之前,先講一下無限滾動(dòng)的原理,首選我們需要之前的,怎么才算滾動(dòng)到底部,然后我們才能去執(zhí)行加載更多的函數(shù)。
關(guān)于高度計(jì)算的幾個(gè)方法
clientHeigt
- 這兩個(gè)屬性用于獲取元素塊可視區(qū)的寬高,該屬性包括內(nèi)邊距 padding,但不包括邊框 border、外邊距 margin 和垂直滾動(dòng)條
scrollHeight
- 一個(gè)元素內(nèi)容高度的度量,包括由于溢出導(dǎo)致的視圖中不可見內(nèi)容,也就是一個(gè)元素寬的實(shí)際高度,包含被滾動(dòng)條卷走的部分。具體看下圖:
scrollTop
- 滾動(dòng)條卷走的高度。,參考下圖:
綜上
得出滾動(dòng)條到達(dá)底部的計(jì)算公式為:clientHeight + scrollTop == scrollHeight
,知道這個(gè)之后,我們寫邏輯就容易多了,只需要在滾動(dòng)條到達(dá)底部的時(shí)候,重新取獲取數(shù)據(jù)就可以了。
目錄結(jié)構(gòu)
App.vue
無限滾動(dòng)首選需要一個(gè)固定高度的盒子然后設(shè)置 style="overflow: auto" 然后可以根據(jù)需要加上滾動(dòng)結(jié)束的限制,比如loading等
<template> <div id="app"> //外層包裹盒子 <div class="infinite-list" v-infinite-scroll.loading.complated.immediate="load" style="overflow: auto" ref="infiniteList" > <ul> <li v-for="i in count" class="infinite-list-item">{{ i }}</li> </ul> //加載中 <p v-if="loading && !complated" class="text">加載中...</p> //結(jié)束了 <p v-if="complated" class="text">沒有更多了</p> </div> </div> </div> </template> <script> import Velocity from "velocity-animate"; import { DatePicker } from "./components/DatePicker/index"; export default { name: "App", components: { DatePicker, }, data() { count: 1, loading: false, complated: false, }; }, methods: { //滾動(dòng)到底部的處理邏輯 load() { // 以下是定時(shí)器模擬異步數(shù)據(jù)請(qǐng)求,可根據(jù)自己的需求進(jìn)行變更 this.loading = true; setTimeout(() => { if (this.count >= 15) { this.complated = true; return; } this.count += 3; this.loading = false; }, 1000); }, }, }; </script> <style lang="less"> #app { .infinite-list { height: 300px; width: 500px; border: 1px solid red; li { height: 50px; background: #e8f3fe; margin: 10px; color: #7dbcfc; text-align: center; line-height: 50px; } .text { color: green; text-align: center; line-height: 50px; } } } </style>
./components/v-infinite-scroll/index.js
import { checkArriveBottom } from "./utils"; export default { install(Vue) { Vue.directive("infinite-scroll", { // 指令在插入的時(shí)候會(huì)執(zhí)行一次 inserted: function (el, binding, vnode) { const fn = binding.value; const context = vnode.context; let timer = null; // 指令的值必須是一個(gè)函數(shù),我們好執(zhí)行回調(diào) if (typeof fn != "function") { throw new Error("指令value必須為函數(shù)"); } // 事件處理函數(shù) function handleScroll() { // 判斷滾動(dòng)條到達(dá)底部了,才開始執(zhí)行回調(diào) if (checkArriveBottom(el)) { // 執(zhí)行回調(diào)的時(shí)候,要把this指向組件實(shí)例 fn.bind(context)(); } } // 將滾動(dòng)處理函數(shù)掛載到對(duì)應(yīng)組件實(shí)例上面,便于組件更新的時(shí)候,對(duì)設(shè)置了loading和complate屬性進(jìn)行移除事件綁定 context.handleScroll = handleScroll; // 如果設(shè)置有immediate說明立即執(zhí)行,則立即執(zhí)行回調(diào),直到將內(nèi)容撐滿內(nèi)容區(qū) if (binding?.modifiers?.immediate) { timer = setInterval(() => { // 子元素的總高度大于設(shè)置指令的父級(jí)包裹元素就表示填滿了可視區(qū),停止加載 const childScrollHeight = el.firstElementChild.scrollHeight; if (childScrollHeight >= el.clientHeight) { return clearInterval(timer); } handleScroll(); }, 1500); } // 綁定滾動(dòng)處理函數(shù) el.addEventListener("scroll", context.handleScroll); }, // 組件更新的時(shí)候,會(huì)不斷觸發(fā)(最明顯就是data中的響應(yīng)式數(shù)據(jù)變化,會(huì)繼續(xù)執(zhí)行update方法) update(el, binding, vnode) { const context = vnode.context; // 如果加載中或者已經(jīng)加載完了,就移除滾動(dòng)事件 if ( (binding?.modifiers?.complated && context.complated) || (binding?.modifiers?.loading && context.loading) ) { el.removeEventListener("scroll", context.handleScroll); } else { // 當(dāng)loading和complate都是false的時(shí)候,表示可以繼續(xù)加載 el.addEventListener("scroll", context.handleScroll); } }, }); }, };
./components/v-infinite-scroll/utils.js
/** * @Description 用于判斷滾動(dòng)條是否到達(dá)底部 * @param { Element } * @return { Boolean } **/ export function checkArriveBottom(el) { const clientHeight = el.clientHeight; const scrollTop = el.scrollTop; const scrollHeight = el.scrollHeight; //可以設(shè)置>=就行,這里也可以設(shè)置距離底部一定距離,自定義,不一定非要到達(dá)底部 return clientHeight + scrollTop >= scrollHeight; }
./components/v-infinite-scroll/main.js
import Vue from "vue"; import App from "./App.vue"; import vInfiniteScroll from "./components/v-infinite-scroll"; Vue.use(vInfiniteScroll); Vue.use(myUi); new Vue({ render: (h) => h(App), }).$mount("#app");
總結(jié)
完成上述指令,需要先閱讀官網(wǎng)自定義指令文檔,搞懂具體指令的一些鉤子函數(shù)的用途以及觸發(fā)時(shí)機(jī),還有就是參數(shù)的意義,鏈接放這里cn.vuejs.org/v2/guide/cu…
到此這篇關(guān)于手寫vue無限滾動(dòng)指令的文章就介紹到這了,更多相關(guān)vue無限滾動(dòng)指令內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Vue 無限滾動(dòng)加載指令實(shí)現(xiàn)方法
- Vue.js 的移動(dòng)端組件庫mint-ui實(shí)現(xiàn)無限滾動(dòng)加載更多的方法
- vue實(shí)現(xiàn)滾動(dòng)加載的表格
- Vue實(shí)現(xiàn)下拉滾動(dòng)加載數(shù)據(jù)的示例
- 通過原生vue添加滾動(dòng)加載更多功能
- vue 使用鼠標(biāo)滾動(dòng)加載數(shù)據(jù)的例子
- vue指令做滾動(dòng)加載和監(jiān)聽等
- 簡單方法實(shí)現(xiàn)Vue?無限滾動(dòng)組件示例
- 基于Vue3實(shí)現(xiàn)無限滾動(dòng)組件的示例代碼
- 基于Vue實(shí)現(xiàn)卡片無限滾動(dòng)動(dòng)畫
- Vue中實(shí)現(xiàn)滾動(dòng)加載與無限滾動(dòng)
相關(guān)文章
vue使用$store.commit() undefined報(bào)錯(cuò)的解決
這篇文章主要介紹了vue使用$store.commit() undefined報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06VUE 實(shí)現(xiàn)動(dòng)態(tài)給對(duì)象增加屬性,并觸發(fā)視圖更新操作示例
這篇文章主要介紹了VUE 實(shí)現(xiàn)動(dòng)態(tài)給對(duì)象增加屬性,并觸發(fā)視圖更新操作,涉及vue.js對(duì)象屬性動(dòng)態(tài)操作及視圖更新相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-11-11適用于 Vue 的播放器組件Vue-Video-Player操作
這篇文章主要介紹了適用于 Vue 的播放器組件Vue-Video-Player操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-11-11淺談Vue數(shù)據(jù)響應(yīng)思路之?dāng)?shù)組
這篇文章主要介紹了淺談Vue數(shù)據(jù)響應(yīng)思路之?dāng)?shù)組,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-11-11利用Vite搭建Vue3+ElementUI-Plus項(xiàng)目的全過程
vue3如今已經(jīng)成為默認(rèn)版本了,相信大多數(shù)公司已經(jīng)全面擁抱vue3了,下面這篇文章主要給大家介紹了關(guān)于利用Vite搭建Vue3+ElementUI-Plus項(xiàng)目的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07vue+element創(chuàng)建動(dòng)態(tài)的form表單及動(dòng)態(tài)生成表格的行和列
這篇文章主要介紹了vue+element創(chuàng)建動(dòng)態(tài)的form表單及動(dòng)態(tài)生成表格的行和列 ,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05Vue3格式化Volar報(bào)錯(cuò)的原因分析與解決
Volar 與vetur相同,volar是一個(gè)針對(duì)vue的vscode插件,下面這篇文章主要給大家介紹了關(guān)于Vue3格式化Volar報(bào)錯(cuò)的原因分析與解決方法,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06