<em id="09ttv"></em>
    <sup id="09ttv"><pre id="09ttv"></pre></sup>
    <dd id="09ttv"></dd>

        • 實(shí)現(xiàn)一個(gè)Vue自定義指令懶加載

          2020-5-16    seo達(dá)人

          什么是圖片懶加載

          當(dāng)我們向下滾動(dòng)的時(shí)候圖片資源才被請(qǐng)求到,這也就是我們本次要實(shí)現(xiàn)的效果,進(jìn)入頁(yè)面的時(shí)候,只請(qǐng)求可視區(qū)域的圖片資源這也就是懶加載。


          比如我們加載一個(gè)頁(yè)面,這個(gè)頁(yè)面很長(zhǎng)很長(zhǎng),長(zhǎng)到我們的瀏覽器可視區(qū)域裝不下,那么懶加載就是優(yōu)先加載可視區(qū)域的內(nèi)容,其他部分等進(jìn)入了可視區(qū)域在加載。


          這個(gè)功能非常常見,你打開淘寶的首頁(yè),向下滾動(dòng),就會(huì)看到會(huì)有圖片不斷的加載;你在百度中搜索圖片,結(jié)果肯定成千上萬(wàn)條,不可能所有的都一下子加載出來(lái)的,很重要的原因就是會(huì)有性能問(wèn)題。你可以在Network中查看,在頁(yè)面滾動(dòng)的時(shí)候,會(huì)看到圖片一張張加載出來(lái)。


          lazyLoad


          為什么要做圖片懶加載

          懶加載是一種網(wǎng)頁(yè)性能優(yōu)化的方式,它能極大的提升用戶體驗(yàn)。就比如說(shuō)圖片,圖片一直是影響網(wǎng)頁(yè)性能的主要元兇,現(xiàn)在一張圖片超過(guò)幾兆已經(jīng)是很經(jīng)常的事了。如果每次進(jìn)入頁(yè)面就請(qǐng)求所有的圖片資源,那么可能等圖片加載出來(lái)用戶也早就走了。所以,我們需要懶加載,進(jìn)入頁(yè)面的時(shí)候,只請(qǐng)求可視區(qū)域的圖片資源。


          總結(jié)出來(lái)就兩個(gè)點(diǎn):


          1.全部加載的話會(huì)影響用戶體驗(yàn)


          2.浪費(fèi)用戶的流量,有些用戶并不像全部看完,全部加載會(huì)耗費(fèi)大量流量。


          懶加載原理

          圖片的標(biāo)簽是 img標(biāo)簽,圖片的來(lái)源主要是 src屬性,瀏覽器是否發(fā)起加載圖片的請(qǐng)求是根據(jù)是否有src屬性決定的。


          所以可以從 img標(biāo)簽的 src屬性入手,在沒進(jìn)到可視區(qū)域的時(shí)候,就先不給 img 標(biāo)簽的 src屬性賦值。


          懶加載實(shí)現(xiàn)

          實(shí)現(xiàn)效果圖:


          imgLazyLoad


          <!DOCTYPE html>

          <html lang="en">

          <head>

             <meta charset="UTF-8">

             <meta name="viewport" content="width=device-width, initial-scale=1.0">

             <title>Document</title>

             <style>

                 div {

                     display: flex;

                     flex-direction: column;

                 }

                 img {

                     width: 100%;

                     height: 300px;

                 }

             </style>

          </head>

          <body>

             <div>

                 <img data-src="https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657907683.jpeg">

                 <img data-src="https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657913523.jpeg">

                 <img data-src="https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657925550.jpeg">

                 <img data-src="https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657930289.jpeg">

                 <img data-src="https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657934750.jpeg">

                 <img data-src="https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657918315.jpeg">

             </div>

          </body>


          </html>

          監(jiān)聽 scroll 事件判斷元素是否進(jìn)入視口

          const imgs = [...document.getElementsByTagName('img')];

          let n = 0;


          lazyload();


          function throttle(fn, wait) {

             let timer = null;

             return function(...args) {

                 if(!timer) {

                     timer = setTimeout(() => {

                         timer = null;

                         fn.apply(this, args)

                     }, wait)

                 }

             }

          }

           

          function lazyload() {

             var innerHeight = window.innerHeight;

             var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;

             for(let i = n; i < imgs.length; i++) {

                 if(imgs[i].offsetTop < innerHeight + scrollTop) {

                     imgs[i].src = imgs[i].getAttribute("data-src");

                     n = i + 1;

                 }

                 

             }

          }

          window.addEventListener('scroll', throttle(lazyload, 200));

          可能會(huì)存在下面幾個(gè)問(wèn)題:


          每次滑動(dòng)都要執(zhí)行一次循環(huán),如果有1000多個(gè)圖片,性能會(huì)很差

          每次讀取 scrollTop 都會(huì)引起回流

          scrollTop跟DOM的嵌套關(guān)系有關(guān),應(yīng)該根據(jù)getboundingclientrect獲取

          滑到最后的時(shí)候刷新,會(huì)看到所有的圖片都加載了

          IntersectionObserver

          Intersection Observer API提供了一種異步觀察目標(biāo)元素與祖先元素或文檔viewport的交集中的變化的方法。


          創(chuàng)建一個(gè) IntersectionObserver對(duì)象,并傳入相應(yīng)參數(shù)和回調(diào)用函數(shù),該回調(diào)函數(shù)將會(huì)在目標(biāo)(target)元素和根(root)元素的交集大小超過(guò)閾值(threshold)規(guī)定的大小時(shí)候被執(zhí)行。


          var observer = new IntersectionObserver(callback, options);

          IntersectionObserver是瀏覽器原生提供的構(gòu)造函數(shù),接受兩個(gè)參數(shù):callback是可見性變化時(shí)的回調(diào)函數(shù)(即目標(biāo)元素出現(xiàn)在root選項(xiàng)指定的元素中可見時(shí),回調(diào)函數(shù)將會(huì)被執(zhí)行),option是配置對(duì)象(該參數(shù)可選)。


          返回的 observer是一個(gè)觀察器實(shí)例。實(shí)例的 observe 方法可以指定觀察哪個(gè)DOM節(jié)點(diǎn)。


          具體的用法可以 查看 MDN文檔


          const imgs = [...document.getElementsByTagName('img')];

          // 當(dāng)監(jiān)聽的元素進(jìn)入可視范圍內(nèi)的會(huì)觸發(fā)回調(diào)

          if(IntersectionObserver) {

              // 創(chuàng)建一個(gè) intersection observer

              let lazyImageObserver = new IntersectionObserver((entries, observer) => {

                  entries.forEach((entry, index) => {

                      let lazyImage = entry.target;

                      // 相交率,默認(rèn)是相對(duì)于瀏覽器視窗

                      if(entry.intersectionRatio > 0) {

                         lazyImage.src = lazyImage.getAttribute('data-src');

                         // 當(dāng)前圖片加載完之后需要去掉監(jiān)聽

                          lazyImageObserver.unobserve(lazyImage);

                      }


                  })

              })

              for(let i = 0; i < imgs.length; i++) {

                 lazyImageObserver.observe(imgs[i]);

              }

          }

          源碼地址-codePen點(diǎn)擊預(yù)覽

          vue自定義指令-懶加載

          Vue自定義指令

          下面的api來(lái)自官網(wǎng)自定義指令:


          鉤子函數(shù)

          bind: 只調(diào)用一次,指令第一次綁定到元素時(shí)調(diào)用。在這里可以進(jìn)行一次性的初始化設(shè)置。

          inserted: 被綁定元素插入父節(jié)點(diǎn)時(shí)調(diào)用 (僅保證父節(jié)點(diǎn)存在,但不一定已被插入文檔中)。

          update: 所在組件的 VNode 更新時(shí)調(diào)用,但是可能發(fā)生在其子 VNode 更新之前。指令的值可能發(fā)生了改變,也可能沒有。但是你可以通過(guò)比較更新前后的值來(lái)忽略不必要的模板更新

          componentUpdated: 指令所在組件的 VNode 及其子 VNode 全部更新后調(diào)用。

          unbind: 只調(diào)用一次,指令與元素解綁時(shí)調(diào)用。

          鉤子函數(shù)參數(shù)

          指令鉤子函數(shù)會(huì)被傳入以下參數(shù):


          el:指令所綁定的元素,可以用來(lái)直接操作 DOM。

          binding:一個(gè)對(duì)象,包含以下 property:


          name:指令名,不包括 v- 前綴。

          value:指令的綁定值,例如:v-my-directive="1 + 1" 中,綁定值為 2。

          oldValue:指令綁定的前一個(gè)值,僅在 update 和 componentUpdated 鉤子中可用。無(wú)論值是否改變都可用。

          expression:字符串形式的指令表達(dá)式。例如 v-my-directive="1 + 1" 中,表達(dá)式為 "1 + 1"。

          arg:傳給指令的參數(shù),可選。例如 v-my-directive:foo 中,參數(shù)為 "foo"。

          modifiers:一個(gè)包含修飾符的對(duì)象。例如:v-my-directive.foo.bar 中,修飾符對(duì)象為 { foo: true, bar: true }。

          vnode:Vue 編譯生成的虛擬節(jié)點(diǎn)。

          oldVnode:上一個(gè)虛擬節(jié)點(diǎn),僅在 update 和 componentUpdated 鉤子中可用。

          實(shí)現(xiàn) v-lazyload 指令

          <!DOCTYPE html>

          <html lang="en">

             <head>

                 <meta charset="UTF-8" />

                 <meta name="viewport" content="width=device-width, initial-scale=1.0" />

                 <title>Document</title>

                 <style>

                     img {

                         width: 100%;

                         height: 300px;

                     }

                 </style>

             </head>

             <body>

                 <div id="app">

                     <p v-for="item in imgs" :key="item">

                         <img v-lazyload="item">

                     </p>

                 </div>

             </body>

             <script src="https://cdn.jsdelivr.net/npm/vue"></script>

             <script>

                 Vue.directive("lazyload", {

                     // 指令的定義

                     bind: function(el, binding) {

          日歷

          鏈接

          個(gè)人資料

          存檔

          婷婷久久综合九色综合九七| 国产精品对白刺激久久久| 香蕉久久av一区二区三区| 三上悠亚久久精品| 久久精品二区| 99久久精品国内| 亚洲日本va午夜中文字幕久久| 久久人人爽人人爽人人片AV不 | 欧美亚洲色综久久精品国产| 久久99精品久久久久久动态图| 91久久精品无码一区二区毛片| 开心久久婷婷综合中文字幕| 久久久噜噜噜久久中文字幕色伊伊 | 狠狠色综合久久久久尤物| 国内精品久久久久影院薰衣草| 色综合久久精品中文字幕首页| 日本强好片久久久久久AAA | 蜜臀久久99精品久久久久久| 色综合久久无码中文字幕| 国产高潮久久免费观看| 国产成人精品久久二区二区 | 久久精品国产网红主播| 久久无码国产| 久久青草国产手机看片福利盒子| 免费精品国产日韩热久久| 精品99久久aaa一级毛片| 国产精品禁18久久久夂久| 97久久国产综合精品女不卡| 国产高潮国产高潮久久久91 | 少妇精品久久久一区二区三区| 久久久久99精品成人片| 久久精品国产免费| 亚洲天堂久久精品| 97久久天天综合色天天综合色hd| 东方aⅴ免费观看久久av | 久久WWW免费人成—看片| 91精品久久久久久无码| 国产精品久久成人影院| 国内精品久久国产大陆| 久久久精品免费国产四虎| 精品久久久久中文字幕日本|