實(shí)現(xiàn)一個(gè)簡(jiǎn)單的vue無限加載指令方法
vue 中的自定義指令是對(duì)底層 dom 進(jìn)行操作,下面以實(shí)現(xiàn)滾動(dòng)到底部加載數(shù)據(jù),實(shí)現(xiàn)無限加載來介紹如何自定義一個(gè)簡(jiǎn)單的指令。
無限加載的原理是通過對(duì)滾動(dòng)事件的監(jiān)聽,每一次滾動(dòng)都要獲取到已滾動(dòng)的距離,如果滾動(dòng)的距離加上瀏覽器窗口高度,會(huì)大于等于內(nèi)容高度,就觸發(fā)函數(shù)加載數(shù)據(jù)。
先介紹不使用 vue 的情況如何實(shí)現(xiàn)無限加載。
不使用框架
首先是html:
<!DOCTYPE html><html lang="en">
<head><meta charset="UTF-8">
<title>實(shí)現(xiàn)滾動(dòng)加載</title>
<style>
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
li, ul {
list-style: none;
}
.container {
width: 980px;
margin: 0 auto;
}
.news__item {
height: 80px;
margin-bottom: 20px;
border: 1px solid #eee;
}</style>
</head>
<body>
<div class="container">
<ul class="news" id="news">
<li class="news__item">1、hello world</li>
<li class="news__item">2、hello world</li>
<li class="news__item">3、hello world</li>
<li class="news__item">4、hello world</li>
<li class="news__item">5、hello world</li>
<li class="news__item">6、hello world</li>
<li class="news__item">7、hello world</li>
<li class="news__item">8、hello world</li>
<li class="news__item">9、hello world</li>
<li class="news__item">10、hello world</li>
</ul>
</div>
</body>
</html>
打開瀏覽器,調(diào)整下瀏覽器窗口高度,讓頁(yè)面可以滾動(dòng)。
先了解三個(gè)變量
- document.body.scrollTop 滾動(dòng)條滾動(dòng)的距離
- window.innerHeight 瀏覽器窗口高度
- document.body.clientHeight 內(nèi)容高度
對(duì)應(yīng)上面的原理就是
window.addEventListener('scroll', function() {
var scrollTop = document.body.scrollTop;
if(scrollTop + window.innerHeight >= document.body.clientHeight) {
// 觸發(fā)加載數(shù)據(jù)
loadMore();
}
});
function loadMore() {
console.log('加載數(shù)據(jù)')'
}
loadMore() 函數(shù)就是從接口獲取到數(shù)據(jù),組裝 html,插入到原先到節(jié)點(diǎn)后面。
// 表示列表的序號(hào)
var index = 10;
function loadMore() {
var content = '';
for(var i=0; i< 10; i++) {
content += '<li class="news__item">'+(++index)+'、hello world</li>'
}
var node = document.getElementById('news');
// 向節(jié)點(diǎn)內(nèi)插入新生成的數(shù)據(jù)
var oldContent = node.innerHTML;
node.innerHTML = oldContent+content;
}
這樣就實(shí)現(xiàn)了無限加載。
在 vue 中使用指令實(shí)現(xiàn)
為什么要用指令實(shí)現(xiàn)呢?好像只有指令是可以獲取到底層 dom 的?而實(shí)現(xiàn)無限加載,是需要拿到內(nèi)容高度的。
首先初始化一個(gè)項(xiàng)目,添加一個(gè)組件,用來顯示列表。
// components/Index.vue
<template>
<div>
<ul class="news">
<li class="news__item" v-for="(news, index) in newslist">
{{index}}-{{news.title}}
</li>
</ul>
</div>
</template>
<style>
.news__item {
height: 80px;
border: 1px solid #ccc;
margin-bottom: 20px;
}
</style>
<script>
export default{
data(){
return{
newslist: [
{title: 'hello world'},
{title: 'hello world'},
{title: 'hello world'},
{title: 'hello world'},
{title: 'hello world'},
{title: 'hello world'},
{title: 'hello world'},
{title: 'hello world'},
{title: 'hello world'},
{title: 'hello world'}
]
}
}
}
</script>
OK,現(xiàn)在開始編寫指令。從傳統(tǒng)實(shí)現(xiàn)中,我們了解到要注冊(cè)對(duì)滾動(dòng)事件對(duì)監(jiān)聽,同時(shí)拿到內(nèi)容高度。
directives: {
scroll: {
bind: function (el, binding){
window.addEventListener('scroll', ()=> {
if(document.body.scrollTop + window.innerHeight >= el.clientHeight) {
console.log('load data');
}
})
}
}
}
首先是在組件內(nèi)注冊(cè)了 scroll 指令,然后在指令第一次綁定到組件時(shí),也就是對(duì)應(yīng)著 bind鉤子,注冊(cè)滾動(dòng)監(jiān)聽。
鉤子函數(shù)就是一些生命周期改變時(shí)會(huì)調(diào)用的函數(shù)。bind 在第一次綁定到組件時(shí)調(diào)用、unbind 在指令與組件解綁時(shí)調(diào)用。
還可以注意到 bind 對(duì)應(yīng)到函數(shù)有兩個(gè)參數(shù),el 和 binding,這是鉤子函數(shù)參數(shù),比如 el 對(duì)應(yīng)綁定的節(jié)點(diǎn),binding 有很多數(shù)據(jù),比如傳給指令的參數(shù)等。
下面的el.clientHeight就是表示獲取綁定指令的這個(gè)節(jié)點(diǎn)的內(nèi)容高度。
和之前一樣,判斷滾動(dòng)的高度加上窗口高度是否大于內(nèi)容高度。
綁定指令到節(jié)點(diǎn)上:
<template>
<div v-scroll="loadMore">
<ul class="news">
<li class="news__item" v-for="(news, index) in newslist">
{{index}}-{{news.title}}
</li>
</ul>
</div>
</template>
可以看到給指令傳了一個(gè)值,這個(gè)值就是加載數(shù)據(jù)的函數(shù):
methods: {
loadMore() {
let newAry = [];
for(let i = 0; i < 10; i++) {
newAry.push({title: 'hello world'})
}
this.newslist = [...this.newslist, ...newAry];
}
}
當(dāng)然,現(xiàn)在在滾動(dòng)到底部時(shí),只會(huì)打印load data,只要把這里改成調(diào)用函數(shù)就OK了:
window.addEventListener('scroll', ()=> {
if(document.body.scrollTop + window.innerHeight >= el.clientHeight) {
let fnc = binding.value;
fnc();
}
})
v-scroll="loadMore"的 loadMore可以在鉤子函數(shù)參數(shù)的 binding 上拿到。
至此,一個(gè)簡(jiǎn)單的指令就完成了。
優(yōu)化
上面的例子并沒有真正從接口獲取數(shù)據(jù),所以存在一個(gè)隱藏的 bug:當(dāng)接口響應(yīng)很慢的情況,滾動(dòng)到底部正在加載數(shù)據(jù)時(shí),稍微滾動(dòng)一下仍會(huì)觸發(fā)獲取數(shù)據(jù)函數(shù),這會(huì)造成同時(shí)請(qǐng)求多次接口,一次性返回大量數(shù)據(jù)。
解決辦法是添加一個(gè)全局變量 scrollDisable,當(dāng)?shù)谝淮斡|發(fā)加載數(shù)據(jù)函數(shù)時(shí),將該值設(shè)置為 true,根據(jù)該值判斷是否要執(zhí)行加載函數(shù)。
以普通實(shí)現(xiàn)為例:
var scrollDisable = false;
window.addEventListener('scroll', function() {
var scrollTop = document.body.scrollTop;
if(scrollTop + window.innerHeight >= document.body.clientHeight) {
// 觸發(fā)加載數(shù)據(jù)
if(!scrollDisable) {
//
loadMore();
}
}
});
// 表示列表的序號(hào)
var index = 10;
function loadMore() {
// 開始加載數(shù)據(jù),就不能再次觸發(fā)這個(gè)函數(shù)了
scrollDisable = true;
var content = '';
for(var i=0; i< 10; i++) {
content += '<li class="news__item">'+(++index)+'、hello world</li>'
}
var node = document.getElementById('news');
// 向節(jié)點(diǎn)內(nèi)插入新生成的數(shù)據(jù)
var oldContent = node.innerHTML;
node.innerHTML = oldContent+content;
// 插入數(shù)據(jù)完成后
scrollDisable = false;
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Vue利用localStorage本地緩存使頁(yè)面刷新驗(yàn)證碼不清零功能的實(shí)現(xiàn)
這篇文章主要介紹了Vue利用localStorage本地緩存使頁(yè)面刷新驗(yàn)證碼不清零功能的實(shí)現(xiàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
npm install -g @vue/cli安裝vue腳手架報(bào)錯(cuò)問題(一般都能解決)
這篇文章主要介紹了npm install -g @vue/cli安裝vue腳手架報(bào)錯(cuò)問題(一般都能解決),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10
vue.js實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器功能
這篇文章主要為大家詳細(xì)介紹了vue.js實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02
vue項(xiàng)目中應(yīng)用ueditor自定義上傳按鈕功能
這篇文章主要介紹了vue項(xiàng)目中應(yīng)用ueditor自定義上傳按鈕功能,文中以vue-cli生成的項(xiàng)目為例給大家介紹了vue項(xiàng)目中使用ueditor的方法,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-04-04
Vuex利用state保存新聞數(shù)據(jù)實(shí)例
本篇文章主要介紹了Vuex利用state保存新聞數(shù)據(jù)實(shí)例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06

