溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

vue無限加載指令怎么實(shí)現(xiàn)

發(fā)布時(shí)間:2022-11-03 09:44:18 來源:億速云 閱讀:107 作者:iii 欄目:開發(fā)技術(shù)

本文小編為大家詳細(xì)介紹“vue無限加載指令怎么實(shí)現(xiàn)”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“vue無限加載指令怎么實(shí)現(xiàn)”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識(shí)吧。

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)整下瀏覽器窗口高度,讓頁面可以滾動(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;
}

Vue的優(yōu)點(diǎn)

Vue具體輕量級(jí)框架、簡(jiǎn)單易學(xué)、雙向數(shù)據(jù)綁定、組件化、數(shù)據(jù)和結(jié)構(gòu)的分離、虛擬DOM、運(yùn)行速度快等優(yōu)勢(shì),Vue中頁面使用的是局部刷新,不用每次跳轉(zhuǎn)頁面都要請(qǐng)求所有數(shù)據(jù)和dom,可以大大提升訪問速度和用戶體驗(yàn)。

讀到這里,這篇“vue無限加載指令怎么實(shí)現(xiàn)”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

vue
AI