首頁 >web前端 >js教程 >實作簡單的vue無限載入指令的方法

實作簡單的vue無限載入指令的方法

不言
不言原創
2018-06-29 15:55:502666瀏覽

這篇文章主要介紹了關於實現簡單的vue無限加載指令的方法,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

vue 中的自定義指令是對底層dom 進行操作,下面以實現滾動到底部加載數據,實現無限加載來介紹如何自定義一個簡單的指令。

無限載入的原理是透過對滾動事件的監聽,每一次滾動都要獲取到已滾動的距離,如果滾動的距離加上瀏覽器視窗高度,會大於等於內容高度,就觸發函數載入數據。

先介紹不使用 vue 的情況如何實現無限載入。

不使用框架

首先是html:

<!DOCTYPE html><html lang="en">
<head><meta charset="UTF-8">
<title>实现滚动加载</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>
<p 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>
</p>
</body>
</html>

開啟瀏覽器,調整下瀏覽器窗口高度,讓頁面可以捲動。

先了解三個變數

  • document.body.scrollTop 捲軸滾動的距離

  • window. innerHeight 瀏覽器視窗高度

  • document.body.clientHeight 內容高度

對應上面的原理就是

#
window.addEventListener(&#39;scroll&#39;, function() {
 var scrollTop = document.body.scrollTop;
 if(scrollTop + window.innerHeight >= document.body.clientHeight) {
  // 触发加载数据    
  loadMore();
 }
});
function loadMore() {
 console.log(&#39;加载数据&#39;)&#39;
}

loadMore() 函數就是從介面取得到數據,組裝html,插入到原先到節點後面。

// 表示列表的序号
var index = 10;
function loadMore() {
 var content = &#39;&#39;;
 for(var i=0; i< 10; i++) {
  content += &#39;<li class="news__item">&#39;+(++index)+&#39;、hello world</li>&#39;  
 }
 var node = document.getElementById(&#39;news&#39;);
 // 向节点内插入新生成的数据  
 var oldContent =   node.innerHTML;
 node.innerHTML = oldContent+content;
}

這樣就實作了無限載入。

在 vue 中使用指令實作

為什麼要用指令實作呢?好像只有指令是可以取得到底層 dom 的?而實現無限加載,是需要拿到內容高度的。

先初始化一個項目,加入一個元件,用來顯示清單。

// components/Index.vue
<template>
 <p>
  <ul class="news">
   <li class="news__item" v-for="(news, index) in newslist">
    {{index}}-{{news.title}}
   </li>
  </ul>
 </p>
</template>
<style>
 .news__item {
  height: 80px;
  border: 1px solid #ccc;
  margin-bottom: 20px;
 }
</style>
<script>
 export default{
  data(){
   return{
    newslist: [
     {title: &#39;hello world&#39;},
     {title: &#39;hello world&#39;},
     {title: &#39;hello world&#39;},
     {title: &#39;hello world&#39;},
     {title: &#39;hello world&#39;},
     {title: &#39;hello world&#39;},
     {title: &#39;hello world&#39;},
     {title: &#39;hello world&#39;},
     {title: &#39;hello world&#39;},
     {title: &#39;hello world&#39;}
    ]
   }
  }
 }
</script>

OK,現在開始寫指令。從傳統實作中,我們了解到要註冊對滾動事件對監聽,同時拿到內容高度。

directives: {
 scroll: {
  bind: function (el, binding){
   window.addEventListener(&#39;scroll&#39;, ()=> {
    if(document.body.scrollTop + window.innerHeight >= el.clientHeight) {
     console.log(&#39;load data&#39;);
    }
   })
  }
 }
}

首先是在元​​件內註冊了scroll 指令,然後在指令第一次綁定到元件時,也就是對應bind鉤子,註冊滾動監聽。

鉤子函數就是一些生命週期改變時會呼叫的函數。 bind 在第一次綁定到元件時呼叫、unbind 在指令與元件解綁時呼叫。

也可以注意到bind 對應到函數有兩個參數,el 和binding,這是鉤子函數參數,例如el 對應綁定的節點,binding 有很多數據,例如傳給指令的參數等。

下面的el.clientHeight就是表示取得綁定指令的這個節點的內容高度。

和之前一樣,判斷捲動的高度加上視窗高度是否大於內容高度。

綁定指令到節點上:

<template>
 <p v-scroll="loadMore">
  <ul class="news">
   <li class="news__item" v-for="(news, index) in newslist">
    {{index}}-{{news.title}}
   </li>
  </ul>
 </p>
</template>

可以看到給指令傳了一個值,這個值就是載入資料的函數:

methods: {
 loadMore() {
  let newAry = [];
  for(let i = 0; i < 10; i++) {
   newAry.push({title: &#39;hello world&#39;})
  }
  this.newslist = [...this.newslist, ...newAry];
 }
}

當然,現在捲動到底部時,只會列印load data,只要把這裡改成呼叫函數就OK了:

 window.addEventListener(&#39;scroll&#39;, ()=> { 
 if(document.body.scrollTop + window.innerHeight >= el.clientHeight) {  
  let fnc = binding.value;  
  fnc(); 
 }
})

v-scroll="loadMore"的loadMore可以在鉤子函數參數的binding 上拿到。

至此,一個簡單的指令就完成了。

優化

上面的範例並沒有真正從介面取得數據,所以存在一個隱藏的bug:當介面回應很慢的情況,捲動到底部正在加載資料時,稍微滾動一下仍會觸發獲取資料函數,這會造成同時請求多次接口,一次返回大量資料。

解決方法是新增一個全域變數 scrollDisable,當第一次觸發載入資料函數時,將該值設為 true,根據該值判斷是否要執行載入函數。

以普通實作為例:

var scrollDisable = false;
window.addEventListener(&#39;scroll&#39;, function() {
 var scrollTop = document.body.scrollTop;
 if(scrollTop + window.innerHeight >= document.body.clientHeight) {
  // 触发加载数据    
  if(!scrollDisable) {
   // 
   loadMore(); 
  } 
 }
});
// 表示列表的序号
var index = 10;
function loadMore() {
  // 开始加载数据,就不能再次触发这个函数了
 scrollDisable = true;
 var content = &#39;&#39;;
 for(var i=0; i< 10; i++) {
  content += &#39;<li class="news__item">&#39;+(++index)+&#39;、hello world</li>&#39;  
 }
 var node = document.getElementById(&#39;news&#39;);
 // 向节点内插入新生成的数据  
 var oldContent =   node.innerHTML;
 node.innerHTML = oldContent+content;
 // 插入数据完成后  
 scrollDisable = false;
}

#以上就是本文的全部內容,希望對大家的學習有所幫助,更相關內容請關注PHP中文網!

相關推薦:

關於Vue2 Vue-cli中使用Typescript的設定介紹

##關於Vue評論框架的實現(父元件的實作)

以上是實作簡單的vue無限載入指令的方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn