基于IntersectionObserver的图片懒加载实现 发表于 2018-10-08 1234567891011121314151617181920212223242526<!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>图片懒加载</title> <link href="./css/style.css" rel="stylesheet"/></head><body> <div id="view"> <img data-src="http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1301/05/c0/17135331_1357355776882.jpg" class="lazy-image"/> <img data-src="http://f.hiphotos.baidu.com/zhidao/pic/item/eac4b74543a982267a3d54978a82b9014b90eb86.jpg" class="lazy-image"/> <img data-src="http://pic1.win4000.com/wallpaper/2/58b61f7dc6c1d.jpg" class="lazy-image"/> <img data-src="http://file03.16sucai.com/2017/1100/16sucai_p20161106032_0c2.JPG" class="lazy-image"/> <img data-src="http://imgsrc.baidu.com/image/c0%3Dpixel_huitu%2C0%2C0%2C294%2C40/sign=5a7938d38acb39dbd5cd6f16b96e6c48/aec379310a55b3196c79de4c48a98226cffc1702.jpg" class="lazy-image"/> <img data-src="http://c.hiphotos.baidu.com/zhidao/pic/item/8d5494eef01f3a2987a8062f9f25bc315d607ceb.jpg" class="lazy-image"/> </div></body><link href="./css/style.css" rel="stylesheet"/><script src="js/lazy-image.js"></script><script> console.log(document.documentElement.clientHeight) new LazyImage('.lazy-image')</script></html> 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475class LazyImage { constructor(selector) { // 懒记载图片列表,将伪数组转为数组,以便可以使用数组的api this.lazyImages = Array.prototype.slice.call(document.querySelectorAll(selector)) this.init() } inViewShow() { // 不支持IntersectionObserver api的情况下判断图片是否出现在可视区域内 let len = this.lazyImages.length for(let i = 0; i < len; i++) { let lazyImage = this.lazyImages[i] const rect = lazyImage.getBoundingClientRect() // 出现在视野的时候加载图片 if(rect.top < document.documentElement.clientHeight) { lazyImage.src = lazyImage.dataset.src // 移除掉已经显示的 this.lazyImages.splice(i, 1) len-- i-- if(this.lazyImages.length === 0) { // 如果全部都加载完 则去掉滚动事件监听 document.removeEventListener('scroll', this._throttleFn) } } } } throttle(fn, delay = 15, mustRun = 30) { let t_start = null let timer = null let context = this return function() { let t_current = +(new Date()) let args = Array.prototype.slice.call(arguments) clearTimeout(timer) if(!t_start) { t_start = t_current } if(t_current - t_start > mustRun) { fn.apply(context, args) t_start = t_current } else { timer = setTimeout(() => { fn.apply(context, args) }, delay) } } } init() { // 通过IntersectionObserver api判断图片是否出现在可视区域内,不需要监听Scroll来判断 if ("IntersectionObserver" in window) { let lazyImageObserver = new IntersectionObserver((entries, observer) => { entries.forEach((entry, index) => { // 如果元素可见 if (entry.isIntersecting) { let lazyImage = entry.target lazyImage.src = lazyImage.dataset.src lazyImageObserver.unobserve(lazyImage) // this.lazyImages.splice(index, 1) } }) }) this.lazyImages.forEach(function(lazyImage) { lazyImageObserver.observe(lazyImage); }) } else { this.inViewShow() this._throttleFn = this.throttle(this.inViewShow) document.addEventListener('scroll', this._throttleFn) } } } 1234567891011121314151617181920212223html,body { height: 100%; width: 100%; margin: 0;}#view { color: red; width: 200px; height: 300px}.lazy-image { background: url('../img/loading.gif') no-repeat center;}img{ margin-top: 100px; background-size: cover; background-position: center; width: 490px; height: 242px;}