懒加载、预加载IntersectionObserver和监听滚动

使用场景

移动端下拉滚动加载图片的时候,通常是使用监听scroll或者使用setInterval来判断,元素是否进入视图,其中scroll由于其特别大的计算量,会有性能问题,而setInterval由于其有间歇期,也会出现体验问题。

IntersectionObserver

允许你追踪目标元素与其祖先元素或视窗的交叉状态。IntersectionObserver API 是异步的,不随着目标元素的滚动同步触发。 即只有线程空闲下来,才会执行观察器。这意味着,这个观察器的优先级非常低,只在其他任务执行完,浏览器有了空闲才会执行。

代码演示

<body>
    <div style="height: 1800px;width:100%; text-align: center;">
        <h3>监听目标元素与祖先或视口交叉状态的手段</h3>
        <p>./image/preview.jpg</p>
    </div>
  
    <img class="imageLoad" alt="图片懒加载">
    <img class="imageLoad" alt="图片懒加载">
    <img class="imageLoad" alt="图片懒加载">
    <img class="imageLoad" alt="图片懒加载">
    <img class="imageLoad" alt="图片懒加载">
    <img class="imageLoad" alt="图片懒加载">
    <img class="imageLoad" alt="图片懒加载">
    <img class="imageLoad" alt="图片懒加载">
    <img class="imageLoad" alt="图片懒加载">
    <img class="imageLoad" alt="图片懒加载">
    <img class="imageLoad" alt="图片懒加载">
    <img class="imageLoad" alt="图片懒加载">
    <img class="imageLoad" alt="图片懒加载">
    <img class="imageLoad" alt="图片懒加载">
    <img class="imageLoad" alt="图片懒加载">

    <script type="module">
        import { Intersection } from './IntersectionOberver.js'
        import { watchScroll } from './监听滚动实现懒加载.js'
        // watchScroll('.imageLoad')
        Intersection('.imageLoad')
    </script>
</body>
export const Intersection = (name) => {
    const img = document.querySelectorAll(name)
    let index = 0
    const options = {
        threshold: [0],//threshold:属性决定相交比例为多少时,触发回调函数。取值为 0 ~ 1,或者 0 ~ 1的数组。
        rootMargin: "300px",//rootMargin: 类似于 CSS 的 margin 属性。用来缩小或扩大 rootBounds,从而影响相交的触发 
        root: null,//root:设置监视器的根节点,不传则默认为视口。
    }
    /*
        entries的属性
        time:发生相交到相应的时间,毫秒。
        rootBounds:根元素矩形区域的信息,如果没有设置根元素则返回null,图中蓝色部分区域。
        boundingClientRect:目标元素的矩形区域的信息,图中黑色边框的区域。
        intersectionRect:目标元素与视口(或根元素)的交叉区域的信息,图中蓝色方块和粉红色方块相交的区域。
        isIntersecting:目标元素与根元素是否相交
        intersectionRatio:目标元素与视口(或根元素)的相交比例。
        target:目标元素。
    */
    const iso = new IntersectionObserver(entries => {

        entries.forEach(v => {
            if (v.isIntersecting) {
                if (index >= 2) index = 0
                index++
                v.target.setAttribute('src', `./image/image${index}.jpg`)
                iso.unobserve(v.target)
            }
        })

    }, options)

    // 开启观察
    img.forEach(element => {
        iso.observe(element)
    });
}

效果展示

懒加载、预加载IntersectionObserver和监听滚动_第1张图片
可以看到当元素与视口rootBounds=300px时,触发回调
懒加载、预加载IntersectionObserver和监听滚动_第2张图片

scroll方式


const thorttle = (callback,wait=500) => {
    let timer = null 
    let licence = true
    const _this = this
    return (...args) => {
        if (licence) {
            timer = setTimeout(() => {
                callback.call(_this, args)
                licence = true
                clearTimeout(timer)
            },wait)
        }
        licence = false
    }
}
//getBoundingClientRect 方法会使浏览器发生回流和重绘,性能消耗稍大,但兼容性比 Intersection Observer 要好。
export const watchScroll = (name) => {
    const img = document.querySelectorAll(name)
    //document.documentElement.clientHeight可视窗口高度
    const vHeight = window.innerHeight || document.documentElement.clientHeight

    document.addEventListener('scroll', thorttle(() => {
        let index = 0
        img.forEach(v => {
            // Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口顶部的位置。
            let {top,height } = v.getBoundingClientRect()
            if (top <= vHeight+100) {
                if (index >= 2) index = 0
                index++
                v.setAttribute('src', `./image/image${index}.jpg`)
            }
        })
    }))
}

你可能感兴趣的:(JS,javascript,前端,css3)