Two practical ways to optimize lazy loading of images in JavaScript


1. Method 1

insert image description here
Highlights:
1.getBoundingClientRect().top > window.innerHeight 图片未出现

2.getBoundingClientRect().top < window.innerHeight 图片出现了

HTML:

<ul>
    ......
    <li>2222222222</li>
    <li>2222222222</li>
    <li>2222222222</li>
    <li>2222222222</li>
    <li>2222222222</li>
    <li>2222222222</li>
    /*先用data-自定义标签,使图片先不加载*/
    <img data-src="./img1.jpg" height="200px"><br>
    <img data-src="./img2.jpg" height="200px" alt=""><br>
    <img data-src="./img3.jpg" height="200px" alt="">
</ul>

JavaScript:

let img = document.querySelectorAll('img')
window.addEventListener('scroll',() => {
    
    
	img.forEach((item) => {
    
    
		//若图片顶部高度小于视窗高度
		if(item.getBoundingClientRect().top < window.innerHeight) {
    
    
			const data_src = item.getAttribute('data-src')
			//则将自定义属性data-src赋值给src属性
			item.setAttribute("src",data_src)
		} 
	})
	console.log("scroll触发了");  //此方法:若加载很多内容,就会导致任务的堆积,影响整体效率
})

Please add image description
We can see that although the lazy loading of the image has been successful, the scroll event is still triggered continuously
, which consumes a lot of resources. Therefore, the most recommended method at present is stillIntersectionObserver

2. Method 2 InterSectionObserver

Highlights:
1.observer.observe(DOM节点) 观察哪个DOM节点

2.observer.unobserve(DOM节点) 取消观察某DOM节点

3.callback目标能看见触发一次;目标元素看不见了又触发一次
HTML as above
JavaScript:

let img = document.querySelectorAll('img')

//此回调:目标能看见触发一次;目标元素看不见了又触发一次
const callback = (entries) => {
    
       //接收一个数组作为参数,数组每一项都和目标元素相关,比如		isIntersecting判断目标元素是否被观察到了,又比如target属性代表该目标元素
    entries.forEach((item) => {
    
    
        //若该目标元素被观察到了
        if(item.isIntersecting) {
    
    
            const img = item.target //目标元素
            const data_src = img.getAttribute('data-src')
            img.setAttribute('src',data_src)
            observer.unobserve(img)  //observer.unobserve(DOM节点)  取消观察某DOM节点
        }
        console.log('触发');
    })
}

const observer = new IntersectionObserver(callback)
//遍历所有img,使得所有img被观察
img.forEach((item) => {
    
    
    observer.observe(item)  //observer.observe(DOM节点)  观察哪个DOM节点
})

Ideas:

  1. Create a new observation instance and observe each image by observing the observe property on the instance.
  2. Define the callback callback function, set the attribute to change when the target image appears

Please add image description
At this point, we see that when all images are lazy loaded (observe cancels observing the DOM node), the scroll event will no longer trigger *

Guess you like

Origin blog.csdn.net/weixin_60297362/article/details/123746981