V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
qzhai
V2EX  ›  程序员

前端一般处理海量数据的渲染有什么优化方案

  •  
  •   qzhai · 2020-01-17 10:13:46 +08:00 · 5944 次点击
    这是一个创建于 1807 天前的主题,其中的信息可能已经有所发展或是发生改变。

    假设,页面需要在一个表格里渲染 几万条 数据。在不分页的情况下有什么好的优化方案来保证页面的流畅度。

    (可能例子有些极端)

    第 1 条附言  ·  2020-01-17 10:49:26 +08:00
    好吧,问题升级,加入我的数据结构很复杂,切渲染的数据高度不一致。

    比如 我有超多条数据是依据某个维度进行分组展示的,每条数据可能还会有父子关系需要在渲染中体现。
    其次它们的高度又不是统一,甚至会有多媒体比如图片的存在(图片又需要在加载后才知道高度)。
    因为是按某个维度进行分组,所以不能分页。
    所以这么复杂的一堆数据需要展示在一个页面里。
    有什么好的优化方案么。
    35 条回复    2020-01-19 09:15:36 +08:00
    Sapp
        1
    Sapp  
       2020-01-17 10:16:22 +08:00
    虚拟列表,简单来说就是 1w 条列表,每次只渲染一部分,之后滚动的时候实时渲染出新的来模拟滚动,这样 dom 实际就是几十条的样子,网上有很多现成的方案
    shijianit
        2
    shijianit  
       2020-01-17 10:17:08 +08:00
    在滚动事件里面做判断,屏幕外面的数据,元素就删除,只保留高度
    zhuzhibin
        3
    zhuzhibin  
       2020-01-17 10:19:43 +08:00 via iPhone
    貌似都在说 lazy load ?
    fancy111
        4
    fancy111  
       2020-01-17 10:20:15 +08:00
    一个表里面几万条? 能看得完吗?为何不分批
    qzhai
        5
    qzhai  
    OP
       2020-01-17 10:20:17 +08:00
    @shijianit 加入,数据嵌套循坏,带子数据,或者每条数据的高度不一致,内容带图片的话判断起来岂不是很麻烦,
    Mozshaw
        6
    Mozshaw  
       2020-01-17 10:20:25 +08:00
    关键词:virtual scroll
    可参考 https://github.com/tangbc/vue-virtual-scroll-list
    zaynex
        7
    zaynex  
       2020-01-17 10:24:44 +08:00
    @qzhai 假设高度不一致的话,这种虚拟列表应该是没法用了。嵌套的数据结构可以利用 web worker 在里面转换成平铺的数组,每次增量渲染若干个节点。
    qzhai
        8
    qzhai  
    OP
       2020-01-17 10:32:07 +08:00
    @Mozshaw 如果渲染数据高度不一致,或者数据结构发复杂 需要提现层级关系比如嵌套 这种有啥好的解决办法么
    momocraft
        9
    momocraft  
       2020-01-17 10:36:15 +08:00
    高度不一致时虚拟列表可能会有什么问题?比如滚动条不准?
    zhw2590582
        10
    zhw2590582  
       2020-01-17 10:41:05 +08:00
    之前也遇到过这个问题,用了这个: https://github.com/bvaughn/react-virtualized
    qzhai
        11
    qzhai  
    OP
       2020-01-17 10:42:18 +08:00
    @momocraft 虚拟列表是通过高度来计算出当前 可视区域内的数据的。如果高度不一致就无法计算可视区域内究竟有多少数据以及是什么数据,也就不能来删除或者渲染数据。
    zhw2590582
        12
    zhw2590582  
       2020-01-17 10:43:09 +08:00
    不过 react-virtualized 的默认是高度要一致,假如高度不一致需要自己提前计算出来再传值到组件里。
    lovedebug
        13
    lovedebug  
       2020-01-17 10:44:58 +08:00
    redbuck
        14
    redbuck  
       2020-01-17 10:45:22 +08:00
    @qzhai 这种类库应该有刷新机制吧,手动刷新下.类似 iscroll,better-scroll 的 refresh.
    diveIntoWork
        15
    diveIntoWork  
       2020-01-17 11:06:59 +08:00
    双缓冲
    linghucq1
        16
    linghucq1  
       2020-01-17 11:20:47 +08:00
    https://juejin.im/post/5de71d1b6fb9a01610795250

    不去计算每一项的高度, 而是计算整页的高度, 虽然封装成组件了, 但是没有实际在项目中使用过...
    ccraohng
        17
    ccraohng  
       2020-01-17 11:26:59 +08:00 via Android
    不是有支持动态高度的么,类似 CellMeasure
    MrJeff
        18
    MrJeff  
       2020-01-17 11:28:00 +08:00
    想办法搞成虚拟列表 否则 DOM 太多 卡爆
    ericgui
        19
    ericgui  
       2020-01-17 11:29:49 +08:00
    @Sapp 能否给个关键词?谢谢
    qzhai
        20
    qzhai  
    OP
       2020-01-17 11:35:11 +08:00
    @ericgui 评论里 甩出来的连接基本都是 他说的原理
    M003
        21
    M003  
       2020-01-17 11:35:32 +08:00
    看过几个虚拟列表,都是需要行高度固定..
    这样才能计算出整个列表的高度,进行渲染.

    曾经也考虑过高度不一致.渲染上千条数据.

    后来放弃了.需求就是个伪需求. 还不如加个搜索框来的快.
    buhi
        22
    buhi  
       2020-01-17 11:35:57 +08:00
    https://github.com/buhichan/react-infinite-virtual-scroll
    我这个支持每行有不一样的高度, 条件是高度渲染后就不能更改(因为会缓存下来), 虽然是 react 的, 但是 vue 的话自己改下的话都能用
    qzhai
        23
    qzhai  
    OP
       2020-01-17 11:37:53 +08:00
    @buhi 哈哈哈。。我用 Angular...
    wanguorui123
        25
    wanguorui123  
       2020-01-17 17:25:06 +08:00
    虚拟列表
    lululau
        26
    lululau  
       2020-01-17 17:28:25 +08:00 via iPhone
    让用户换台 Mac pro
    GrapeCityChina
        27
    GrapeCityChina  
       2020-01-17 17:32:47 +08:00
    懒加载、双缓存机制、canvas 绘制界面... 好吧,我是在说 SpreadJS
    withzhaoyu
        28
    withzhaoyu  
       2020-01-17 17:47:21 +08:00
    核心思路应该就是只渲染可视区域。。。。我大概只用过前面大伙说的 react-virtualized
    YourLord
        29
    YourLord  
       2020-01-17 17:50:33 +08:00 via Android
    打死你的后台同事,直接把全表数据扔给前段也太业余了。
    xiangyuecn
        30
    xiangyuecn  
       2020-01-17 17:52:38 +08:00
    终极优化办法:干掉提需求的人
    Ritr
        31
    Ritr  
       2020-01-17 17:53:39 +08:00
    @withzhaoyu 说的对,没用的 DOM 移除掉不然会很卡
    qzhai
        32
    qzhai  
    OP
       2020-01-17 18:21:38 +08:00
    @YourLord 我们是个协同工具,复杂场景很多这个是正常的需求
    mostkia
        33
    mostkia  
       2020-01-18 13:34:11 +08:00
    可以考虑让后台分页,大量数据一次性加载到 html 是不好的做法,如果考虑到用户体验不允许有换页之类的效果,可以试试 ajax 这类,类似瀑布流的那种按需加载,都是现成的方案,挺成熟的。
    r3m
        34
    r3m  
       2020-01-19 06:14:13 +08:00 via Android
    万条数据具有多媒体数据的 table 可以先在后台缓存好每条数据对应的宽高,或者根据前端具体设备去简单在后台计算好宽高等等,最后把每一行高度数据加上每一行的 id 发送给前端。这个请求的数据量压缩前也只需要占 100kb 以内。之后前端已知宽高就可以就直接套用虚拟列表那一套,在可视范围内 lazy loading 就好了。如果要 loading 之前的可视效果更好一点后台可以顺便在其中传一些文字内容,图片颜色,视频封面颜色之类的基本信息,pinterest 上这种效果就做很好
    ccsulzf0627
        35
    ccsulzf0627  
       2020-01-19 09:15:36 +08:00
    我看老哥是用 angular 的,推荐一下 ag-grid
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2380 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 02:05 · PVG 10:05 · LAX 18:05 · JFK 21:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.