JS懒加载与预加载
正在学习前端的渣渣-小方同学 人气:01、懒加载
1.1、什么是懒加载
懒加载也可以叫做延迟加载,当访问一个页面的时候,先把img元素伙食其他元素的背景图片路径替换成一张大小为1*1px图片的路径(这样只需要请求一次,俗称占位图);
只有当图片出现在浏览器的可视区域内时,才这只图片真正的路径,让图片显示出来,这就是图片懒加载。
1.2、为什么要使用懒加载
当页面很多,内容很丰富的时候,页面很长,图片较多,比如各个商城页面,要是页面载入就一次性加载完毕,就需要等很长的时间
1.3、懒加载的优点
按需加载,页面加载速度快,节约流量,用户体验感好,减少服务器压力
1.4、懒加载的原理
页面中的img元素,如果没有src属性, 浏览器就不会发出请求去下载图片,只有通过javascript设置了图片路径,浏览器才会发送请求。
懒加载的原理就是先在页面中把所有的图片统一使用一张占位图进行占位,把真正的路径存在元素的"data-url"(这个名字起个自己认识好记的就行)属性里,要用的时候就取出来放在src里面
1.5、懒加载的实现步骤
- 首先,不要将图片地址放到src属性中,而是放到其它属性(data-origina)中。
- 页面加载完成后,判断图片是否在用户的视野内,如果在,则将data-original属性中的值取出存放到src属性中
1.6、懒加载的实现方式
<ul> <li><img src="../img/loading.gif" alt="" data-src="../img/1.jpg"></li> <li><img src="../img/loading.gif" alt="" data-src="../img/2.jpg"></li> <li><img src="../img/loading.gif" alt="" data-src="../img/3.jpg"></li> <li><img src="../img/loading.gif" alt="" data-src="../img/4.jpg"></li> <li><img src="../img/loading.gif" alt="" data-src="../img/5.jpg"></li> <li><img src="../img/loading.gif" alt="" data-src="../img/6.jpg"></li> <li><img src="../img/loading.gif" alt="" data-src="../img/7.jpg"></li> <li><img src="../img/loading.gif" alt="" data-src="../img/8.jpg"></li> </ul>
方式1:通过 元素距离顶部的高度 - 滚动条滚动的高度 < =窗口可视化区域高度 进行判断;
/*元素距离顶部的高度-页面被卷去的高度<=浏览器可视区域的高度 如果条件满足,就可以替换图片的src属性 */ //获取图片 const imgArr = document.querySelectorAll("img"); //初始化执行 lazyLoad(); //监听用户是否滚动滚动条,但是这高触发事件,所以需要结合节流优化 window.addEventListener("scroll", throttle(lazyLoad, 2000)); function lazyLoad() { imgArr.forEach(item => { //1、获取图片距离顶部的高度 const imgOffsetTop = item.offsetTop; //2、获取浏览器的可视区域的高度 const wHeight = window.innerHeight; //3、获取页面被卷去的高度 const scrollHeight = document.documentElement.scrollTop; //判断图片是否将要出现 if (imgOffsetTop - scrollHeight <= wHeight) { item.src = item.getAttribute("data-src"); } }) } //节流 function throttle(fun, time = 250) { let lastTime = 0;//最后一次执行的时间 return function (...args) { const now = new Date().getTime();//获取当前的时间 if (now - lastTime >= time) { fun(); lastTime = now; } } }
方式2:getBoundingClientRect()
- 获取元素位置, 这个方法没有参数
- 用于获得页面中某个元素的左,上, 右和下分别相对浏览器视窗的位置。
- 是DOM元素到浏览器可视范围的距离(不包含文档卷起的部分)
- 该函数返回一个0bject对象, 该对象有6个属性: top, lef, right, bottom , width, height;
const imgArr = document.querySelectorAll("img"); //初始化执行 lazyLoad() //监听用户是否滚动滚动条,但是这高触发事件,所以需要结合节流优化 //监听用户是否滚动滚动条,但是这高触发事件,所以需要结合节流优化 window.addEventListener("scroll", throttle(lazyLoad, 2000)); function lazyLoad() { imgArr.forEach(item => { //获取图片和顶部的高度 const imgTop = item.getBoundingClientRect().top; //获取浏览器可视化区域高度 const wHeight = window.innerHeight; //图片和顶部的高度小于浏览器窗口可视化区域的高度 if (imgTop <= wHeight) { //getAttribute获取自定义属性 // item.src = item.getAttribute("data-src"); //也可以使用dataset来获取自定义属性的值 item.src = item.dataset.src; } }) } //节流 function throttle(fun, time = 250) { let lastTime = 0;//最后一次执行的时间 return function (...args) { const now = new Date().getTime();//获取当前的时间 if (now - lastTime >= time) { fun(); lastTime = now; } } }
方式3:IntersectionObserver(callback)构造函数
callback回调触发两次,看见了触发,看不见也触发。
实例有两个方法:
- observe给元素添加观察
- unobserve取消对元素观察
const callback = (res) => { //res是一个数组,所以还需要遍历 console.log(res); res.forEach(item => { //isIntersecting是否在可视区域展示 if (item.isIntersecting) { //获取图片的自定义属性并赋值给src item.target.src = item.target.dataset.src; //替换为真是src地址后取消对它的观察 observe.unobserve(item.target); } }) } //1、实例化构造函数 const observe = new IntersectionObserver(callback); const imgArr = document.querySelectorAll("img"); //遍历所有的图片,给每个图片添加观察 imgArr.forEach(item => { //观察图片 observe.observe(item) })
2、预加载
2.1、什么是预加载
资源预加载是另一个性能优化技术,我们可以使用该技术来预先告知浏览器某些资源可能在将来会被使用到。预加载简单来说就是将所有所需的资源提前请求加载到本地,这样后面在需要用到时就直接从缓存取资源。
2.2、为什么要使用预加载
在网页全部加载之前,对一些主要内容进行加载,以提供给用户更好的体验,减少等待的时间。否则,如果一个页面的内容过于庞大,没有使用预加载技术的页面就会长时间的展现为一片空白,直到所有内容加载完毕。
2.3、实现预加载的方法
<div> <p></p> <img src="../img/1.jpg" alt=""> </div> <script type="text/javascript"> const imgArr = ["../img/2.jpg", "../img/3.jpg", "../img/4.jpg", "../img/5.jpg", "../img/6.jpg", "../img/7.jpg"] const img = document.querySelector("img"); const p = document.querySelector("p"); //定义默认的index的值 let index = 0; p.innerHTML = `实现预加载的效果,我是第${index + 1}张图片`; img.addEventListener("click", (e) => { if (index < imgArr.length) { img.src = imgArr[index]; index++; p.innerHTML = `实现预加载的效果,我是第${index + 1}张图片`; if (index < imgArr.length) { //切换图片后,同时让浏览器提前加载下一张图片 preLoad(imgArr[index]) } } else { confirm("没有图片了") } }, false) //调用预加载函数,页面一开始就加载数组的第一个元素 preLoad(imgArr[0]) //定义预加载函数 function preLoad(src) { //当图片失去焦点后 img.addEventListener("load", () => { //创建一个新的img标签 const imgNew = document.createElement("img"); //给img标签添加src属性为我们传进来的src imgNew.src = src; }) } </script>
加载全部内容