多数据列表分批加载

301 阅读2分钟

前景

通常后端数据返回都会对内容较多的数据进行分页处理,前台只需要传递相关分页标识就可以了。可是这种情况常见于B端的表格展示,那么若我们要做到类似于C端的多数据分批加载有什么响应的处理方式呢?

常见的情况有: 图片懒加载,多数据列表加载

解决思路

为了前端优化,避免一次性加载过多数据的页面渲染,从而导致的页面卡顿问题,通常会只加载一部分数据,然后通过滚动事件,判断触发点是否出现在可视区域,从而二次发送请求

其中,触发点的元素:可以是骨架屏;也可以在加载列表的底部添加一个div元素(height:0px)

实现方法

1. 滚动监听+scrollTop+offsetTop+clientHeight

判断dom顶部是否出现在可视化区域:clientHeight+scrollTop>=元素.offsetTop

例如:图片懒加载。img在没有src属性的时候,是不会对资源进行加载的,其中data-url是自定义属性
<body>
    <img src="./img/pixel.gif" data-url="./img/1.jpeg">
    <img src="./img/pixel.gif" data-url="./img/2.jfif">
    <img src="./img/pixel.gif" data-url="./img/3.jfif">
    <img src="./img/pixel.gif" data-url="./img/4.jfif">
    <img src="./img/pixel.gif" data-url="./img/5.jfif">
    <img src="./img/pixel.gif" data-url="./img/6.webp">

    <script>

        let imgs = document.getElementsByTagName('img')
        // 1. 一上来立即执行一次
        fn()
        // 2. 监听滚动事件
        window.onscroll = lazyload(fn, true)
        function fn() {
            // 获取视口高度和内容的偏移量
            let clietH = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
            var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
            for (let i = 0; i < imgs.length; i++) {
                let x = scrollTop + clietH - imgs[i].offsetTop //当内容的偏移量+视口高度>图片距离内容顶部的偏移量时,说明图片在视口内
                if (x > 0) {
                    imgs[i].src = imgs[i].getAttribute('data-url'); //从dataurl中取出真实的图片地址赋值给url
                }
            }
        }
          // 函数节流
        function lazyload(fn, immediate) {
            let timer = null
            return function () {
                let context = this;
                if (!timer) {
                    timer = setTimeout(() => {
                        fn.apply(this)
                        timer = null
                    }, 200)
                }
            }
        }


    </script>
</body>
————————————————
版权声明:本文为CSDN博主「望屿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/darabiuz/article/details/123151266

2. getBoundingClientRect()

getBoundingClientRect()是获取当前dom元素的相对位置,可获取x,y轴的距离

可视区域的触发点:bound.top<=clientHeight

3. intersectionObserver(浏览器的observer)

这里以react写法举例:

 const scrollRef = useRef(null);
   // 当我的 ref 的 div 到顶的时候,我们进行切换。
   // 如何判断到顶了?
   // 1. getBoundingClientRect();
   // 2. IntersectionObserver();

   useEffect(()=>{
    var intersectionObserver = new IntersectionObserver((entries) => {
        console.log(entries[0].isIntersecting);//该值标识是否出现在可视区域
        onChange && onChange(entries[0].isIntersecting)//此处可以对数据进行二次请求操作
    });

    intersectionObserver.observe(scrollRef.current);

    return () => {
        intersectionObserver.unobserve(scrollRef.current);
        intersectionObserver = void 0;
    }
   }, [])

4. 正对百万级数据的渲染加载(一般不会有这种场景)

1. 虚拟长列表:仅仅在可视化视图区域渲染dom

参考文章:blog.csdn.net/qq_43307723…

2. worker :拆分线程

我理解的意思大概就是说,js是一个单线程,web worker可以分离一个子线程出来,然后将需要大量计算的那部分代码放在这个子线程中去执行,子线程相对于主线程互相独立,所以不会影响到主线程ui的正常渲染,减少了代码阻塞。

worker使用详情:www.ruanyifeng.com/blog/2018/0…

worker的具体运用参考:juejin.cn/post/684490…

额外知识点补充

浏览器的5种observer

** intersectionObserver **:监听一个元素在可视区域的可见性(场景:某元素滚动到xx时,顶部菜单变成浮动固定)

mutationObserve:监听一个元素,子节点的增删改

** resizeObserver **:监听一个元素宽高的改变(运用场景:echarts图表resize动态响应失效的时候,可以尝试这种方式)

performanceObserver:浏览器performance记录数据行为的监听

reportingObserver:对浏览器自动提示的一些警告,干预等行为进行监听