懒加载、预加载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)
    });
}

效果展示

在这里插入图片描述
可以看到当元素与视口rootBounds=300px时,触发回调
在这里插入图片描述

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`)
            }
        })
    }))
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
您可以使用`BackgroundWorker`组件来在滚动滚动界面,具体步骤如下: 1. 创建一个`BackgroundWorker`组件,用于在后台数据。 2. 在滚动条的`Scroll`事件中,检查滚动条位置是否达到了的位置,如果是则启动`BackgroundWorker`组件数据。 3. 在`BackgroundWorker`的`DoWork`事件中,数据并将其存储在一个缓存中。 4. 在`BackgroundWorker`的`RunWorkerCompleted`事件中,将的数据添到界面中。 下面是一个示例代码,可以在滚动滚动列表数据: ```csharp private void Form1_Load(object sender, EventArgs e) { // 初始化滚动条 this.vScrollBar1.Minimum = 0; this.vScrollBar1.Maximum = 1000; this.vScrollBar1.LargeChange = 100; } private void vScrollBar1_Scroll(object sender, ScrollEventArgs e) { // 判断是否需要 if (e.NewValue + this.vScrollBar1.LargeChange >= 800) { // 启动 BackgroundWorker 数据 this.backgroundWorker1.RunWorkerAsync(); } } private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { // 模拟数据 Thread.Sleep(5000); // 将的数据存储在缓存中 List<string> data = new List<string>(); for (int i = 0; i < 50; i++) { data.Add("数据行 " + (i + 1).ToString()); } e.Result = data; } private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // 将的数据添到界面中 if (e.Error == null) { List<string> data = e.Result as List<string>; foreach (string item in data) { this.listBox1.Items.Add(item); } } } ``` 在上面的代码中,我们通过滚动条的`Scroll`事件来检查是否需要数据,如果需要则启动`BackgroundWorker`组件数据。`BackgroundWorker`的`DoWork`事件中模拟了数据的过程,并将数据存储在一个缓存中。最后,在`BackgroundWorker`的`RunWorkerCompleted`事件中将的数据添到界面中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大鲤余

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值