国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

實現一個簡單的vue無限加載指令方法

2019-11-19 18:02:01
字體:
來源:轉載
供稿:網友

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><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>

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

先了解三個變量

  • document.body.scrollTop 滾動條滾動的距離
  • window.innerHeight 瀏覽器窗口高度
  • document.body.clientHeight 內容高度

對應上面的原理就是

window.addEventListener('scroll', function() { var scrollTop = document.body.scrollTop; if(scrollTop + window.innerHeight >= document.body.clientHeight) {  // 觸發加載數據      loadMore(); }});function loadMore() { console.log('加載數據')'}

loadMore() 函數就是從接口獲取到數據,組裝 html,插入到原先到節點后面。

// 表示列表的序號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'); // 向節點內插入新生成的數據   var oldContent =   node.innerHTML; node.innerHTML = oldContent+content;}

這樣就實現了無限加載。

在 vue 中使用指令實現

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

首先初始化一個項目,添加一個組件,用來顯示列表。

// 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,現在開始編寫指令。從傳統實現中,我們了解到要注冊對滾動事件對監聽,同時拿到內容高度。

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

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

鉤子函數就是一些生命周期改變時會調用的函數。bind 在第一次綁定到組件時調用、unbind 在指令與組件解綁時調用。

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

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

和之前一樣,判斷滾動的高度加上窗口高度是否大于內容高度。

綁定指令到節點上:

<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>

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

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

當然,現在在滾動到底部時,只會打印load data,只要把這里改成調用函數就OK了:

 window.addEventListener('scroll', ()=> {  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('scroll', 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 = ''; for(var i=0; i< 10; i++) {  content += '<li class="news__item">'+(++index)+'、hello world</li>'   } var node = document.getElementById('news'); // 向節點內插入新生成的數據   var oldContent =   node.innerHTML; node.innerHTML = oldContent+content; // 插入數據完成后   scrollDisable = false;}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 新巴尔虎右旗| 辉县市| 武穴市| 伊宁县| 普陀区| 郁南县| 临城县| 广昌县| 鸡泽县| 丰县| 泰顺县| 米泉市| 郴州市| 泽州县| 将乐县| 河南省| 永福县| 登封市| 娱乐| 浪卡子县| 栖霞市| 东莞市| 邵阳市| 佛山市| 阜城县| 曲麻莱县| 新建县| 称多县| 台东市| 和林格尔县| 泰和县| 昌都县| 阿鲁科尔沁旗| 湘西| 波密县| 于都县| 乐清市| 青川县| 崇阳县| 马关县| 大宁县|