懒加载:延迟加载,当图片出现在可视区域内,再去进行图片加载,以提升因图片过多引起的加载缓慢的页面加载速度。
一、<image>标签loading属性
image标签自带一个loading属性,这个属性有2个值
eager | 默认值,渲染时图像立即加载 |
lazy | 开启懒加载,当滑动到该区域时图像才加载 |
该属性也可以进行懒加载,但是该属性开启的懒加载会加载两到三个可视页面的图片,不止当前可视区域的图片进行了加载。
兼容性:
二、懒加载
根据原理:当图片出现在可视区域内,再去进行图片加载。需要对滚动进行监控,并判断图片是否进入可视区域。同时我们可以将可视区域的范围增大,再即将进入可视区域进行图片加载,减少进入可视区域后图片正在进行加载或者加载未完成的情况。
1、img标签
<img loading="lazy" datasrc={concat1}></img>
在img标签中我们不给src赋值,并将该处应加载的图片赋值给datasrc,之后需要赋值时将datasrc里的值赋值给src即可。
2、监控滚动条
以react的函数组件为例,在渲染时添加对scroll的监听,要注意在销毁阶段取消监听,减少页面负担。
useEffect(() => {
setTimeout(()=>{
checkImages()
},1)
window.addEventListener('scroll', checkImages)
return ()=>{
window.removeEventListener("scroll", checkImages)
}
}, [])
其中checkImages函数是用来给img标签的src进行赋值。当img的src属性为空是,img将不会进行图片加载的操作,只有当你给src赋值以后她才会对图片进行请求,我们也是利用这一特性去进行懒加载。
const checkImages = () => {
var imgs = document.querySelectorAll('img')
imgs.forEach((item, index)=>{
if(isInClient(item) && item.src === ''){
item.src = item.getAttribute('datasrc')
}
})
}
在其中我们获取页面所有的img标签,并对其进行判断,其中isInClient函数是对图片的位置判断,用src是否有值来判断其是否加载过图片,如果有则不进行再次赋值,避免出现重复加载的情况。
注意:
我们渲染时需要先调用一次checkImages函数,而在第一段代码中的setTimeout就是做了这个事情,这个操作是为了自动显示出第一个可视页面的图片加载,即没有滚动前出现的页面的图片加载,这一步十分重要。
其中这里采用了setTimeout进行了1ms的延迟调用是为了保证dom节点都存在,如果不使用者1ms的延迟,可能在checkImages函数中无法获取到img的节点,也十分重要,在函数组件中出现了这种情况,但类组件中还未试验过。
2、图片位置判断是否需要加载
在checkImages函数中有个函数isInClient,是用来判断图片是否进入了可是区域。
const isInClient = (item) => {
var offset = item.getBoundingClientRect()
var bodyHeight = document.body.offsetHeight
if( (offset.top>0 && offset.top < bodyHeight + (bodyHeight / 2) ) || (offset.bottom > 0 && offset.bottom < bodyHeight + (bodyHeight /2) )){
return true
}
else{
return false
}
}
在这里,我的可视区域高度的判断不止是当前窗口的可是区域,还往上下都延伸了半个可视区域,这样判断是为了上面说的减少进入可视区域后图片正在进行加载或者加载未完成的情况。
至此我的懒加载过程全部完成,如有错误,欢迎指正。