懒加载是一种网页性能优化的方式,它能极大的提高用户体验。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 ( ...  ... );
先加载出如今视窗中的图片, 当页面将要滚动到不在视窗内的图片时,加载图片。性能优化
(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; } }, }