方法一閉包
// // 節流 // // setTimeout+閉包 function throttle(fn, interval = 500) { let timer = null; let firstTime = true; return function(...args) { if (firstTime) { // 第一次加載 fn.apply(this, args); return (firstTime = false); } if (timer) { // 定時器正在執行,跳過 return; } timer = setTimeout(() => { clearTimeout(timer); timer = null; fn.apply(this, args); }, interval); }; } // // 判斷元素是否出如今視口區域 function isElementInViewport(el){ // Element.getBoundingClientRect()方法返回元素的大小及其相對於視口的位置。 // 當滾動位置發生了改變,top和left屬性值就會隨之當即發生變化(所以,它們的值是相對於視口的,而不是絕對的) const {top,height,left,width} = el.getBoundingClientRect(); const w = window.innerWidth || document.documentElement.clientWidth; const h = window.innerHeight || document.documentElement.clientHeight; return { top <= h && (top+height) >=0 && left <= w && (left+width)>=0; } } // lazyLoad function LazyLoad(el, options) { if (!(this instanceof LazyLoad)) { return new LazyLoad(el); } this.setting = Object.assign( {}, { src: 'data-src', srcset: 'data-srcset', selector: '.lazyload' }, options ); if (typeof el === 'string') { el = document.querySelectorAll(el) } this.images=Array.from(el) this.listener=this.loadImage() this.listener() this.initEvent() LazyLoad.prototype= { loadImage(){ return throttle(function(){ let startIndex=0; while(startIndex<this.images.length){ const image = this.images[startIndex] if (isElementInViewport(image)) { const src = image.getAttribute(this.setting.src) const srcset = image.getAttribute(this.setting.srcset) if (image.tagName.toLowerCase()==="img") { if (src) { image.src=src } if (srcset) { image.srcset=srcset } }else { image.style.backgroundImage=`url(${src})` } this.image.splice(startIndex,1) continue } startIndex++ } if (!this.images.length) { this.destroy() } }).bind(this) }, initEvent(){ window.addEventListener('srcoll',this.listener,false) }, destroy(){ window.addEventListener('scroll',this.listener,false) this.images=null; this.listener=null; } } }
方法二app
// lazyLoad function LazyLoad(images, options = {}) { if (!(this instanceof LazyLoad)) { return new LazyLoad(images, options); } this.setting = Object.assign( {}, { src: 'data-src', srcset: 'data-srcset', selector: '.lazyload' }, options ); this.images = images || document.querySelectorAll(this.setting.selector); this.observer = null; this.init(); } LazyLoad.prototype.init = function() { let self = this; let observerConfig = { root: null, rootMargin: '0px', threshold: [0] }; this.observer = new IntersectionObserver(entries => { entries.forEach(entry => { const target = entry.target; if (entry.intersectionRatio > 0) { this.observer.unobserve(target); const src = target.getAttribute(this.setting.src); const srcset = target.getAttribute(this.setting.srcset); if ('img' === target.tagName.toLowerCase()) { if (src) { target.src = src; } if (srcset) { target.srcset = srcset; } } else { target.getElementsByClassName.backgroundImage = `url(${src})`; } } }); }, observerConfig); this.images.forEach(image => this.observer.observe(image)); };