对于页面有很多静态资源的情况下(比如商品图),为了节省用户流量和提高页面性能,可以在用户浏览到当前资源的时候,再对资源进行请求和加载,不仅可以减轻服务器的压力,而且用户体验也好一点
方式1:通过scroll监听滚动,getBoundingClientRect获取位置信息,(这种方式缺点是经常计算元素位置信息,性能较差,可能给你的网站造成相当大的闪烁)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <title></title> <style type="text/css"> .box{margin-top:700px;} .box img{width:100%;height:270px;border:1px solid #ddd;} </style> </head> <body> <div class="box"> <img data-src="https://test.jifenyi.com:9123/htmlPC/10060/images/pointA/banner.jpg" class="js_img"> <img data-src="https://test.jifenyi.com:9123/uxunimg2/cust/shop/17216/goods/pic/2018/09/11/25194778443592045449242.jpg_140x140c.jpg" class="js_img" > <img data-src="https://test.jifenyi.com:9123/uxunimg2/cust/shop/17216/goods/pic/2018/09/11/951689489805364494.jpg_140x140c.jpg" class="js_img" > <img data-src="https://test.jifenyi.com:9123/uxunimg2/cust/shop/17216/goods/pic/2018/09/11/8198878495038442.jpg_140x140c.jpg" class="js_img"> </div> <script type="text/javascript"> var h = document.documentElement.clientHeight; // 视口高度 var js_imgAll = document.querySelectorAll('.js_img') var flag = 0; // 记录已经加载过的图片 window.onload = uploadImg window.onscroll = _throttle(uploadImg, 300) // 检查未加载的图片 function uploadImg() { for(var i = flag; i < js_imgAll.length; i++) { if(_isShow(js_imgAll[i])) { _replacePath(js_imgAll[i]) flag = i } } } // 是否将显示图片 function _isShow(img) { // getBoundingClientRect获取图片大小以及位置 var obj_t = img.getBoundingClientRect().top // 100是为了预加载 if(obj_t <= h + 100) { return true } return false } // 替换图片路径 function _replacePath(obj) { if(!obj.src) { obj.src = obj.getAttribute('data-src') } } // 函数节流,滚动条滚动等频繁的DOM操作,让一个函数不要执行的太频繁,减少一些过快的调用来节流 function _throttle(fn, t) { var flag = true; return function () { if(!flag) return; flag = false; setTimeout(() => { fn.apply(this, arguments) flag = true; }, t) } } </script> </body> </html>
方式2:通过IntersectionObserver,它可以检测一个元素是否可见,能让你知道一个被观测的元素什么时候进入或离开浏览器的视口(目前ios不兼容)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <title></title> <style type="text/css"> .box{margin-top:700px;} .box img{width:100%;height:270px;border:1px solid #ddd;} </style> </head> <body> <div class="box"> <img data-src="https://test.jifenyi.com:9123/htmlPC/10060/images/pointA/banner.jpg" class="js_img"> <img data-src="https://test.jifenyi.com:9123/uxunimg2/cust/shop/17216/goods/pic/2018/09/11/25194778443592045449242.jpg_140x140c.jpg" class="js_img" > <img data-src="https://test.jifenyi.com:9123/uxunimg2/cust/shop/17216/goods/pic/2018/09/11/951689489805364494.jpg_140x140c.jpg" class="js_img" > <img data-src="https://test.jifenyi.com:9123/uxunimg2/cust/shop/17216/goods/pic/2018/09/11/8198878495038442.jpg_140x140c.jpg" class="js_img"> </div> <script type="text/javascript"> var js_imgAll = document.querySelectorAll('.js_img') // IntersectionObserver是浏览器提供的构造函数,callback是可见性变化时的回调函数 var io = new IntersectionObserver(entries => { entries.forEach(item => { // 目标元素的可见比例大于0即出现在可视区 if(item.intersectionRatio > 0) { // 替换路径 _replacePath(item.target) // 停止观察图片 io.unobserve(item.target) } }) }) // 开始观察每个图片 Array.from(js_imgAll).forEach(obj => { io.observe(obj) }) // 替换图片路径 function _replacePath(obj) { if(!obj.src) { obj.src = obj.getAttribute('data-src') } } </script> </body> </html>