使用intersectionObserver实现图片懒加载

634 阅读1分钟

传统实现方式

传统的图片懒加载实现主要是能通过监听容器的onscroll事件,在事件回调中通过getBoundingClientRect方法来获取元素距离视窗左上角的坐标。然后根据屏幕宽高来判断元素与视窗是否有交集。

但是这种方法有一个很大的缺点:onscroll事件是一个频繁执行的事件,其中伴随着大量的计算,由于js是线程的,所以它会影响页面的渲染性能。

IntersectionObserver实现

IntersectionObjser提供了一种异步观察目标元素与其祖先元素或视窗交叉状态的方法。

实现步骤

html,以vue为例

<div class="container">
    <!-- 当此元素出现在视图中时加载图片 -->
    <div class="skeleton" ref="lazyImage" v-if="!showImage">
        这是骨架屏
    </div>
    <!-- 这是真实的图片 -->
    <img src="url" v-else />
</div>

js

new Vue({
    data() {
        return {
            showImage: false,
            url: '图片地址',
            intersection: null,
        }
    },
    // 渲染完成后,才能获取到lazyImage
    mounted() {
        this.intersection = new IntersectionObserver(entries => {
            // 因为我们只监听一个元素,所以这里取第0个
            const current = entries[0]
            // intersectionRatio > 0 时,表示当前元素与视图有交叉
            if (current.intersectionRatio > 0) {
                // 关闭监听
                this.intersection?.disconnect()
                // 创建一个Image对象
                const image = new Image()
                image.src = this.url
                // 当图片加载成功后,显示图片,否则还是是显示骨架屏
                image.onload = () => {
                    this.showImage = true;
                }
            }
        })
        // 开始监听dom元素
        this.intersection.observe(this.$refs.lazyImage)
    }
})

打完收功