整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          手把手教你實現一個Vue自定義指令懶加載

          手把手教你實現一個Vue自定義指令懶加載


          者: 木子星兮i

          轉發鏈接:https://mp.weixin.qq.com/s/36oBZMd-m-2k5EKPghfG3A

          1. 性能收益:瀏覽器加載圖片、decode、渲染都需要耗費資源,懶加載能節約性能消耗,縮短onload事件時間。
          2. 節約帶寬:這個不需要解釋。

          通常,我們在html中展示圖片,會有兩種方式:

          1. img 標簽
          2. css background-image

          img的懶加載實現

          img有兩種方式實現懶加載:

          1. 事件監聽(scroll、resize、orientationChange)
          <!DOCTYPE html>
          <html lang="en">
          <head>
           <meta charset="UTF-8">
           <meta name="viewport" content="width=device-width, initial-scale=1.0">
           <meta http-equiv="X-UA-Compatible" content="ie=edge">
           <title>event</title>
           <style>
           img {
           background: #F1F1FA;
           width: 400px;
           height: 300px;
           display: block;
           margin: 10px auto;
           border: 0;
           }
           </style>
          </head>
          <body>
           <img src="https://ik.imagekit.io/demo/img/image1.jpeg?tr=w-400,h-300" />
           <img src="https://ik.imagekit.io/demo/img/image2.jpeg?tr=w-400,h-300" />
           <img src="https://ik.imagekit.io/demo/img/image3.jpg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image2.jpeg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image3.jpg?tr=w-400,h-300" /> -->
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image4.jpeg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image5.jpeg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image6.jpeg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image7.jpeg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image8.jpeg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image9.jpeg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image10.jpeg?tr=w-400,h-300" />
           <script>
           document.addEventListener("DOMContentLoaded", function() {
           var lazyloadImages=document.querySelectorAll("img.lazy"); 
           var lazyloadThrottleTimeout;
           
           function lazyload () {
           if(lazyloadThrottleTimeout) {
           clearTimeout(lazyloadThrottleTimeout);
           } 
           
           lazyloadThrottleTimeout=setTimeout(function() {
           var scrollTop=window.pageYOffset;
           lazyloadImages.forEach(function(img) {
           if(img.offsetTop < (window.innerHeight + scrollTop)) {
           img.src=img.dataset.src;
           img.classList.remove('lazy');
           }
           });
           if(lazyloadImages.length==0) {
           document.removeEventListener("scroll", lazyload);
           window.removeEventListener("resize", lazyload);
           window.removeEventListener("orientationChange", lazyload);
           }
           }, 20);
           }
           
           document.addEventListener("scroll", lazyload);
           window.addEventListener("resize", lazyload);
           window.addEventListener("orientationChange", lazyload);
           });
           </script>
          </body>
          </html>
          
          1. Intersection Observer(兼容性問題)
          <!DOCTYPE html>
          <html lang="en">
          <head>
           <meta charset="UTF-8">
           <meta name="viewport" content="width=device-width, initial-scale=1.0">
           <meta http-equiv="X-UA-Compatible" content="ie=edge">
           <title>observer</title>
           <style>
           img {
           background: #F1F1FA;
           width: 400px;
           height: 300px;
           display: block;
           margin: 10px auto;
           border: 0;
           }
           </style>
          </head>
          <body>
           <img src="https://ik.imagekit.io/demo/img/image2.jpeg?tr=w-400,h-300" />
           <img src="https://ik.imagekit.io/demo/img/image3.jpg?tr=w-400,h-300" /> -->
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image1.jpeg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image2.jpeg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image3.jpg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image4.jpeg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image5.jpeg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image6.jpeg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image7.jpeg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image8.jpeg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image9.jpeg?tr=w-400,h-300" />
           <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image10.jpeg?tr=w-400,h-300" />
           <script>
           document.addEventListener("DOMContentLoaded", function() {
           var lazyloadImages=document.querySelectorAll(".lazy");
           var imageObserver=new IntersectionObserver(function(entries, observer) {
           entries.forEach(function(entry) {
           if (entry.isIntersecting) {
           var image=entry.target;
           image.src=image.dataset.src;
           image.classList.remove("lazy");
           imageObserver.unobserve(image);
           }
           });
           });
           lazyloadImages.forEach(function(image) {
           imageObserver.observe(image);
           });
           });
           </script>
          </body>
          </html>
          

          background-image的實現

          background-image的實現跟img的原理基本是一樣的,區別是在對class的處理上:

          <!DOCTYPE html>
          <html lang="en">
          <head>
           <meta charset="UTF-8">
           <meta name="viewport" content="width=device-width, initial-scale=1.0">
           <meta http-equiv="X-UA-Compatible" content="ie=edge">
           <title>background</title>
           <style>
           body {
           margin: 0;
           }
           .bg {
           height: 200px;
           }
           #bg-image.lazy {
           background-image: none;
           background-color: #F1F1FA;
           }
           #bg-image {
           background-image: url("https://ik.imagekit.io/demo/img/image1.jpeg?tr=w-400,h-300");
           background-size: 100%;
           }
           </style>
          </head>
          <body>
           <div id="bg-image" class="bg lazy"></div>
           <div id="bg-image" class="bg lazy"></div>
           <div id="bg-image" class="bg lazy"></div>
           <div id="bg-image" class="bg lazy"></div>
           <div id="bg-image" class="bg lazy"></div>
           <div id="bg-image" class="bg lazy"></div>
           <div id="bg-image" class="bg lazy"></div>
           <div id="bg-image" class="bg lazy"></div>
           <script>
           document.addEventListener("DOMContentLoaded", function() {
           var lazyloadImages=document.querySelectorAll(".lazy");
           var imageObserver=new IntersectionObserver(function(entries, observer) {
           entries.forEach(function(entry) {
           if (entry.isIntersecting) {
           var image=entry.target;
           image.classList.remove("lazy");
           imageObserver.unobserve(image);
           }
           });
           });
           lazyloadImages.forEach(function(image) {
           imageObserver.observe(image);
           });
           });
           </script>
          </body>
          </html>
          

          漸進式懶加載

          漸進式懶加載,指的是存在降級處理,通常html形式如下:

          <a href="full.jpg" class="progressive replace">
           <img src="tiny.jpg" class="preview" alt="image" />
          </a>
          

          這樣的代碼會有2個好處:

          1. 如果js執行失敗,可以點擊預覽
          2. 大小與實際圖一致的占位data URI,避免reflow

          最終的代碼如下:

          <!DOCTYPE html>
          <html lang="en">
          <head>
           <meta charset="UTF-8">
           <meta name="viewport" content="width=device-width, initial-scale=1.0">
           <meta http-equiv="X-UA-Compatible" content="ie=edge">
           <title>progressive</title>
           <style>
           a.progressive {
           position: relative;
           display: block;
           overflow: hidden;
           outline: none;
           }
           a.progressive:not(.replace) {
           cursor: default;
           }
           a.progressive img {
           display: block;
           width: 100%;
           max-width: none;
           height: auto;
           border: 0 none;
           }
           a.progressive img.preview {
           filter: blur(2vw);
           transform: scale(1.05);
           }
           a.progressive img.reveal {
           position: absolute;
           left: 0;
           top: 0;
           will-change: transform, opacity;
           animation: reveal 1s ease-out;
           }
           @keyframes reveal {
           0% {transform: scale(1.05); opacity: 0;}
           100% {transform: scale(1); opacity: 1;}
           }
           </style>
          </head>
          <body>
           <a href="http://m.jungjaehyung.com/uploadfile/2024/1009/20241009120959593.jpg" data-srcset="http://m.jungjaehyung.com/uploadfile/2024/1009/20241009120959593.jpg 800w, https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature5big.jpg 1600w" class="progressive replace">
           <img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2NjIpLCBxdWFsaXR5ID0gNzAK/9sAQwAKBwcIBwYKCAgICwoKCw4YEA4NDQ4dFRYRGCMfJSQiHyIhJis3LyYpNCkhIjBBMTQ5Oz4+PiUuRElDPEg3PT47/9sAQwEKCwsODQ4cEBAcOygiKDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7/8AAEQgABQAUAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A5yC3e2S3gM7OEQHdgA57VTuLAPqUoaUk7yM7R2BPSiivS5VN8stjmk2ldGVM3lyshG7bxk0UUV4skk2jdN2P/9k=" class="preview" alt="palm trees" />
           </a>
           <a href="http://m.jungjaehyung.com/uploadfile/2024/1009/20241009121000935.jpg" class="progressive replace">
           <img src="http://lorempixel.com/20/15/nature/2/" class="preview" alt="sunset" />
           </a>
           <a href="http://m.jungjaehyung.com/uploadfile/2024/1009/20241009121001477.jpg" class="progressive replace">
           <img src="http://lorempixel.com/20/15/nature/3/" class="preview" alt="tide" />
           </a>
           <a href="http://m.jungjaehyung.com/uploadfile/2024/1009/20241009120959593.jpg" data-srcset="http://m.jungjaehyung.com/uploadfile/2024/1009/20241009120959593.jpg 800w, https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature5big.jpg 1600w" class="progressive replace">
           <img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2NjIpLCBxdWFsaXR5ID0gNzAK/9sAQwAKBwcIBwYKCAgICwoKCw4YEA4NDQ4dFRYRGCMfJSQiHyIhJis3LyYpNCkhIjBBMTQ5Oz4+PiUuRElDPEg3PT47/9sAQwEKCwsODQ4cEBAcOygiKDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7/8AAEQgABQAUAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A5yC3e2S3gM7OEQHdgA57VTuLAPqUoaUk7yM7R2BPSiivS5VN8stjmk2ldGVM3lyshG7bxk0UUV4skk2jdN2P/9k=" class="preview" alt="palm trees" />
           </a>
           <a href="http://m.jungjaehyung.com/uploadfile/2024/1009/20241009121000935.jpg" class="progressive replace">
           <img src="http://lorempixel.com/20/15/nature/2/" class="preview" alt="sunset" />
           </a>
           <a href="http://m.jungjaehyung.com/uploadfile/2024/1009/20241009121001477.jpg" class="progressive replace">
           <img src="http://lorempixel.com/20/15/nature/3/" class="preview" alt="tide" />
           </a>
           <script>
           window.addEventListener('load', function() {
           var pItem=document.getElementsByClassName('progressive replace'), timer;
           window.addEventListener('scroll', scroller, false);
           window.addEventListener('resize', scroller, false);
           inView();
           function scroller(e) {
           timer=timer || setTimeout(function() {
           timer=null;
           requestAnimationFrame(inView);
           }, 300);
           }
           function inView() {
           var scrollTop=window.pageYOffset;
           var innerHeight=window.innerHeight;
           var p=0;
           while (p < pItem.length) {
           var offsetTop=pItem[p].offsetTop;
           if (offsetTop < (scrollTop + innerHeight)) {
           loadFullImage(pItem[p]);
           pItem[p].classList.remove('replace');
           }
           else p++;
           }
           }
           function loadFullImage(item) {
           var img=new Image();
           if (item.dataset) {
           img.srcset=item.dataset.srcset || '';
           img.sizes=item.dataset.sizes || '';
           }
           img.src=item.href;
           img.className='reveal';
           if (img.complete) addImg();
           else img.onload=addImg;
           function addImg() {
           item.addEventListener('click', function(e) { e.preventDefault(); }, false);
           item.appendChild(img).addEventListener('animationend', function(e) {
           var pImg=item.querySelector('img.preview');
           if (pImg) {
           e.target.alt=pImg.alt || '';
           item.removeChild(pImg);
           e.target.classList.remove('reveal');
           }
           });
           }
           }
           }, false);
           </script>
          </body>
          </html>
          

          現成庫

          推薦下面這個庫,使用非常簡單:https://www.npmjs.com/package/lozad

          歡迎關注微信公眾號:編程成長記

          為 `src` 賦值成一個通用的預覽圖,下拉時候再動態賦值成正式的圖片。

          `preview.png`是預覽圖片,比較小,加載很快,而且很多圖片都共用這個`preview.png`,加載一次即可。

          待頁面下拉,圖片顯示出來時,再去替換`src`為`data-realsrc`的值。

          <img src="preview.png" data-realsrc="abc.png"/>

          這里為何要用`data-`開頭的屬性值?

          所有 HTML 中自定義的屬性,都應該用`data-`開頭,因為`data-`開頭的屬性瀏覽器渲染的時候會忽略掉,提高渲染性能。


          主站蜘蛛池模板: 亚洲国产老鸭窝一区二区三区| 亚洲国产一区国产亚洲| 国产精品乱码一区二区三| 国产vr一区二区在线观看| 男插女高潮一区二区| 无码人妻一区二区三区免费看 | 国产品无码一区二区三区在线| 中文字幕一区二区免费| 精品久久久久久中文字幕一区| 亚洲码一区二区三区| 亚洲不卡av不卡一区二区| 国产高清在线精品一区小说| 亚洲国产精品一区二区九九 | 激情综合丝袜美女一区二区| 亚洲av永久无码一区二区三区| 日本不卡一区二区三区视频| 东京热无码一区二区三区av| 精品中文字幕一区二区三区四区| 成人h动漫精品一区二区无码| 精品一区二区三区四区在线播放 | 日日摸夜夜添一区| 国产精品久久一区二区三区| 久久久91精品国产一区二区| 日本免费一区二区久久人人澡| 久久精品免费一区二区三区| 久久精品一区二区免费看| 日本在线一区二区| 无码少妇一区二区| 精品福利视频一区二区三区| 成人区精品一区二区不卡亚洲| 在线观看一区二区三区av| 丝袜美腿一区二区三区| 国产成人一区二区三区精品久久| 在线观看国产一区亚洲bd| 日亚毛片免费乱码不卡一区| 相泽亚洲一区中文字幕| 亚洲国产一区二区a毛片| 色噜噜狠狠一区二区三区| 亚洲精品无码一区二区| 免费观看日本污污ww网站一区| 国产精品一区二区三区免费|