懶加載是一種網頁性能優化的方式,它能極大的提高用戶體驗。css
假如訪問某個頁面,加載這個頁面所有的圖片(即便這些圖片並不處在用戶的當前的視窗中),在弱網環境或者網速較慢的環境下,這些「冗餘」圖片的下載會佔用用戶原本就很是有限的帶寬,影響用戶體驗因此對於網站的圖片,優化的方法就是懶加載(按需加載)。vue
進入頁面的時候,只請求可視區域的圖片資源, 不在可視區域內的圖片,等將要出現時動態加載。node
將img標籤src設置爲一張默認小圖片,而後定義data-src
(這個屬性能夠自定義命名,我才用data-src)屬性指向真實的圖片。src
需設置一張默認的圖片,不然當src
爲空時也會向服務器發送一次請求。git
設置data-src, 經過js加載真正的圖片。github
// img-load.css img[data-src] { filter: blur(0.2em); } img { filter: blur(0em); transition: filter 0.5s; }
// img-load.js function lazyLoad(){ const imageToLazy = document.querySelectorAll('img[data-src]'); const loadImage = function (image) { image.setAttribute('src', image.getAttribute('data-src')); image.addEventListener('load', function() { image.removeAttribute("data-src"); }) } imageToLazy.forEach(function(image){ loadImage(image); }) } lazyLoad(); return ( ... ![](deafult.png) ... );
先加載出如今視窗中的圖片, 當頁面將要滾動到不在視窗內的圖片時,加載圖片。性能優化
(function lazyLoad(){ let observer; const imageToLazy = document.querySelectorAll('img[data-src]'); const loadImage = function (image) { image.setAttribute('src', image.getAttribute('data-src')); image.addEventListener('load', function() { image.removeAttribute("data-src"); }) } if (window.IntersectionObserver) { observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting || entry.intersectionRatio > 0) { loadImage(entry.target); observer.unobserve(entry.target); } }); }); } imageToLazy.forEach(function(image){ if (window.IntersectionObserver && observer) { observer.observe(image); } else { loadImage(image); } }) })();
添加scroll
事件實現圖片懶加載。當頁面滾動時,scroll
函數會被高頻觸發,須要經過節流或者requestAnimationFrame優化性能。服務器
判斷圖片是否將要出如今可視區也可根據getBoundingClientRect()
判斷函數
const imgs = document.getElementsByTagName("img"); const imgLength = imgs.length; let currentIndex = 0; //存儲圖片加載到的位置,避免每次都從第一張圖片開始遍歷 const clientHeight = document.documentElement.clientHeight; //可見區域高度 const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; //滾動條距離頂部高度 function lazyload(event) { for (let i = currentIndex; i < imgLength; i++) { if (clientHeight + scrollTop > imgs[i].offsetTop) { if (imgs[i].getAttribute("src") == "default.jpg") { imgs[i].src = img[i].getAttribute("data-src"); } currentIndex = i + 1; } } } window.addEventListener('scroll',throttle(lazyload, 500, 1000));
let timer = null; let observer; if (window.IntersectionObserver) { observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting || entry.intersectionRatio > 0) { if (!entry.target.isLoaded) { showImage(entry.target, entry.target.data_src); } } }); }); } function showImage(el, imgSrc) { const img = new Image(); img.src = imgSrc; img.onload = () => { el.src = imgSrc; el.isLoaded = true; }; } export default { inserted(el, binding, vnode) { el.data_src = binding.value; if (window.IntersectionObserver && observer) { clearTimeout(timer); observer.observe(el); const vm = vnode.context; timer = setTimeout(() => { vm.$on('hook:beforeDestroy', () => { observer.disconnect(); }); }, 20); } else { el.src = binding.value; } }, update(el, binding) { if (window.IntersectionObserver && observer) { el.isLoaded = el.data_src !== binding.value; el.data_src = binding.value; } else { el.src = binding.value; } }, }