前端处理10万条数据
发布日期:2021-11-21 16:35:32 浏览次数:10 分类:技术文章

本文共 2123 字,大约阅读时间需要 7 分钟。

1. 采用懒加载+分页(前端维护懒加载的数据分发和分页);

2. 使用虚拟滚动技术(目前react的antd4.0已支持虚拟滚动的select长列表)

懒加载和分页方式一般用于做长列表优化, 类似于表格的分页功能, 具体思路就是用户每次只加载能看见的数据, 当滚动到底部时再去加载下一页的数据.

虚拟滚动技术也可以用来优化长列表, 其核心思路就是每次只渲染可视区域的列表数,当滚动后动态的追加元素并通过顶部padding来撑起整个滚动内容,实现思路也非常简单.

第一种方案:

1. 懒加载+分页方案 懒加载的实现主要是通过监听窗口的滚动, 当某一个占位元素可见之后去加载下一个数据,原理如下:

这里我们通过监听window的scroll事件以及对poll元素使用getBoundingClientRect来获取poll元素相对于可视窗口的距离, 从而自己实现一个懒加载方案.

在滚动的过程汇总我们还需要注意一个问题就是当用户往回滚动时, 实际上是不需要做任何处理的,所以我们需要加一个单向锁, 具体代码如下:
function scrollAndLoading() {
    if(window.scrollY > prevY) { // 判断用户是否向下滚动
        prevY = window.scrollY
        if(poll.current.getBoundingClientRect().top <= window.innerHeight) {
            // 请求下一页数据
        }
    }
}

useEffect(() => {

    // something code
    const getData = debounce(scrollAndLoading, 300)
    window.addEventListener('scroll', getData, false)
    return () => {
        window.removeEventListener('scroll', getData, false)
    }
}, [])

其中prevY存储的是窗口上一次滚动的距离, 只有在向下滚动并且滚动高度大于上一次时才更新其值.

至于分页的逻辑, 原生javascript实现分页也很简单, 通过定义几个维度:

curPage当前的页数

pageSize 每一页展示的数量
data 传入的数据量

分页代码:

let data = [];
let curPage = 1;
let pageSize = 16;
let prevY = 0;

// other code...

function scrollAndLoading() {

    if(window.scrollY > prevY) { // 判断用户是否向下滚动
        prevY = window.scrollY
        if(poll.current.getBoundingClientRect().top <= window.innerHeight) {
            curPage++
            setList(searchData.slice(0, pageSize * curPage))
        }
    }
}

2. 防抖函数实现
function debounce(fn, time) {
    return function(args) {
        let that = this
        clearTimeout(fn.tid)
        fn.tid = setTimeout(() => {
            fn.call(that, args)
        }, time);
    }
}

3.搜索实现

const handleSearch = (v) => {
    curPage = 1;
    prevY = 0;
    searchData = data.filter((item, i) => {
        // 采用正则来做匹配, 后期支持前端模糊搜索
        let reg = new RegExp(v, 'gi')
        return reg.test(item.title)
    })
    setList(searchData.slice(0, pageSize * curPage))
}

第二种方案:

可以使用js缓冲器来分片处理100万条数据, 思路代码如下:
function multistep(steps,args,callback){
    var tasks = steps.concat();

    setTimeout(function(){

        var task = tasks.shift();
        task.apply(null, args || []); //调用Apply参数必须是数组

        if(tasks.length > 0){

            setTimeout(arguments.callee, 25);
        }else{
            callback();
        }
    },25);
}

还可以通过web worker来将需要在前端进行大量计算的逻辑移入进去, 保证js主进程的快速响应, 让web worker线程在后台计算, 计算完成后再通过web worker的通信机制来通知主进程, 比如模糊搜索等, 我们还可以对搜索算法进一步优化,比如二分法等。

转载地址:https://blog.csdn.net/yyychocolate/article/details/108056991 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:JS单线程
下一篇:HTTP 状态码

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2024年04月23日 21时36分02秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

Spring注解驱动开发第32讲——拦截器链的执行过程 2021-06-30
Spring注解驱动开发第33讲——AOP原理总结 2021-06-30
Spring注解驱动开发第34讲——你了解基于注解版的声明式事务吗? 2021-06-30
Spring注解驱动开发第35讲——声明式事务原理的源码分析 2021-06-30
Spring注解驱动开发第36讲——或许,这是你以前没看过的从源码角度理解BeanFactoryPostProcessor的原理 2021-06-30
Spring注解驱动开发第37讲——你知道Spring中BeanDefinitionRegistryPostProcessor是如何执行的吗? 2021-06-30
Spring注解驱动开发第38讲——你知道ApplicationListener的用法吗? 2021-06-30
Spring注解驱动开发第39讲——你不知道的ApplicationListener的原理 2021-06-30
Spring注解驱动开发第40讲——你晓得@EventListener这个注解的原理吗? 2021-06-30
Spring注解驱动开发第41讲——Spring IOC容器创建源码解析(一)之BeanFactory的创建以及预准备工作 2021-06-30
Spring注解驱动开发第42讲——Spring IOC容器创建源码解析(二)之执行BeanFactoryPostProcessor 2021-06-30
Spring注解驱动开发第43讲——Spring IOC容器创建源码解析(三)之注册BeanPostProcessor 2021-06-30
Spring注解驱动开发第44讲——Spring IOC容器创建源码解析(四)之初始化MessageSource组件 2021-06-30
Spring注解驱动开发第45讲——Spring IOC容器创建源码解析(五)之初始化事件派发器 2021-06-30
Spring注解驱动开发第46讲——Spring IOC容器创建源码解析(六)之初始化所有剩下的单实例bean(上) 2021-06-30
Spring注解驱动开发第47讲——Spring IOC容器创建源码解析(七)之初始化所有剩下的单实例bean(下) 2021-06-30
Spring注解驱动开发第48讲——Spring IOC容器创建源码解析(八)之完成BeanFactory的初始化创建工作,最终完成容器创建 2021-06-30
Spring注解驱动开发第49讲——Spring IOC容器创建源码解析(九)之Spring IOC容器创建源码总结 2021-06-30
Spring注解驱动开发第50讲——带你走进Servlet 3.0的世界 2021-06-30
Spring注解驱动开发第51讲——ServletContainerInitializer来了,傻孩子们,快跑啊! 2021-06-30