超大表格组件滚动渲染优化

news2024/11/16 3:48:42

引用自 摸鱼wiki

背景

业务中需要渲染一个最多有100+列的表格,由于表格使用原生dom实现,因此会出现同屏有近1000个单元格同时绘制,在快速滑动时页面会产生卡顿,影响用户体验。

方案

如下图所示,由于用户显示屏区域有限,实际上并不能同时看见超大表格的所有列,因此可以考虑虚拟滚动的设计思路,仅渲染用户可视区域内的单元格及其内容,区域外的尽可能减少渲染。

于是可以考虑把表格拆分成三个区域:

  1. 可视区域:即图中绿色标注单元格,这部分单元格用户可见,必须完整渲染
  2. 缓冲区域:即图中蓝色标注单元格,这部分单元格用户不可见,但在用户左右快速滑动时有可能可见,因此可以进行预渲染
  3. 隐藏区域:即图中红色标注单元格,这部分单元格用户不可见,且在一般情况下会一直保持不可见状态,因此可以省略其渲染

在这里插入图片描述
针对上述三种单元格类型,可以有对应三种渲染策略:

  1. 可视单元格:正常渲染
  2. 缓冲单元格:正常渲染
  3. 隐藏单元格:相邻单元格合并成一个大的空白div(图中的紫色单元格),拼接在两端,由于是一个空白div,因此渲染性能损耗极低

通过上述方法可以看到,原本一个12列的表格,在渲染的时候仅会渲染10列,包含6列可视区+2列缓冲区 + 2列填充区(消耗几乎为0),理论渲染效率提高15%-30%。由于用户视口大小是固定的,因此无论表格有多少列,同时都只会有10列单元格在实时渲染,列数越多则性能提升越大。

实施

1. 使用IntersectionObserver监听表头

new IntersectionObserver(
  (entries) => {
    let isChange = false;
    entries.forEach((e) => {
      const columnKey = e.target.getAttribute('column-key');
      if (!columnKey) return;
      if (e.intersectionRatio > 0.0) {
        this.visibleHeader.add(columnKey);
        isChange = true;
      } else {
        isChange = true;
        this.visibleHeader.delete(columnKey);
      }
    });
    if (isChange) {
      this.visibleHeaderChange.value = Date.now();
    }
  },
  {
    root,
    threshold: [0, 1],
  },
);

2. 计算前后空白宽度拼接行渲染数据

const displayCols = []
// 可视区域
for (const col of this.visibleHeader) {
	displayCols.push(col);
}
// 缓冲区域
displayCols.unshift(prevCacheCol);
displayCols.push(nextCacheCol);
// 不可见区域
displayCols.unshift(prevEmptyCol);
displayCols.push(nextEmptyCol);

3. 使用ResizeObserver监听行高变化

由于横向虚拟,行高仅与可视区+缓冲区的单元格相关,来回滚动时可能会导致行高发生变化导致抖动,因此需要给行元素添加resize监听,获取最大行高并记录,减少横向滚动的抖动

new ResizeObserver((entries) => {
  entries.forEach((entry) => {
    const rowKey = entry.target.getAttribute('data-id');
    if (!rowKey) return;
    const { height } = entry.contentRect;
    row.height = max(height, row.height)
  });
});

效果

设备:MacBook M1Pro + 120Hz高刷屏
数据量:单表90列数据

改造前:
在这里插入图片描述
改造后:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1047905.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode算法二叉树—222. 完全二叉树的节点个数

目录 222. 完全二叉树的节点个数 - 力扣(LeetCode) 代码: 运行结果: 给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。 完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能…

opencv开发环境配置

一、下载安装 打开opencv官方网站,opencv管网地址,选择下载的版本 双击安装包,选择安装路径,进行安装 安装完毕后,打开 注意:环境变量配置的bin路径不是build/bin,而是build/x64/vc16/bin …

chrome扩展程序开发请求接口报错

解决HTTPS站点请求HTTP接口服务后报错&#xff1a;the content must be served over HTTPS Mixed Content: The page at <URL> was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint <URL>. This content should also be served over HTTPS…

网络知识:内网、外网、宽带、带宽、流量、网速之间的联系?

相信很多人都不知道内网、外网、宽带、带宽、流量、网速之间的区别与联系&#xff0c;今天小编给大家介绍一下&#xff0c;希望对大家能有所帮助&#xff01; 一.带宽与宽带的区别是什么&#xff1f; 带宽是量词&#xff0c;指的是网速的大小&#xff0c;比如1Mbps的意思是一兆…

数据库系统课设——基于python+pyqt5+mysql的酒店管理系统(可直接运行)--GUI编程(2)

几个月之前写的一个项目&#xff0c;通过这个项目&#xff0c;你能学到关于数据库的触发器知识&#xff0c;python的基本语法&#xff0c;python一些第三方库的使用&#xff0c;包括python如何将前后端连接起来&#xff08;界面和数据&#xff09;&#xff0c;还有界面的设计等…

Guava限流器原理浅析

文章目录 基本知识限流器的类图使用示例 原理解析限流整体流程问题驱动1、限流器创建的时候会初始化令牌吗&#xff1f;2、令牌是如何放到桶里的&#xff1f;3、如果要获取的令牌数大于桶里的令牌数会怎么样4、令牌数量的更新会有并发问题吗 总结 实际工作中难免有限流的场景。…

振弦采集仪结合无线中继扩展应用岩土工程监测的解决方案

振弦采集仪结合无线中继扩展应用岩土工程监测的解决方案 岩土工程监测是现代工程建设不可或缺的一部分&#xff0c;其目的是确保工程安全和稳定。然而&#xff0c;在进行监测时常常面临许多挑战。传统的岩土工程监测方法需要大量的人力、物力和时间&#xff0c;而且往往难以采…

顽固污渍一键去除,还有紫外线除菌功能,希亦超声波清洗机体验

日常生活中&#xff0c; 眼镜、牙刷等小物件的清洗该怎么清洗呢&#xff1f;如果使用肥皂水或者专业清洁剂来处理&#xff0c;还需要使用一些小工具来帮助清洁&#xff0c;比如清洁布、棉签等&#xff0c;不仅会很麻烦&#xff0c;而且需要频繁擦拭&#xff0c;镜片等物品光滑的…

601-体育馆的人流量

文章目录 601-体育馆的人流量1. 题目2. 思路3. 解决4. 运行结果 601-体育馆的人流量 1. 题目 2. 思路 思路&#xff1a;查询Stadium表中人流量超过100的记录&#xff0c;将查询结果与自身的临时表连接&#xff0c;再使用where获得满足条件的记录 查询Stadium表中人流量超过10…

现代数据中心发明人Luiz André Barroso去世,享年59岁,Jeff Dean、劈柴发推悼念

Luiz Andr Barroso因故去世&#xff0c;享年59岁。他作为现代云计算行业的奠基人&#xff0c;为谷歌的发展做出了不可磨灭的贡献。 数据中心发明人&#xff0c;云计算的奠基人&#xff0c;谷歌22年老兵Luiz Andr Barroso于9月16日意外去世&#xff0c;享年59岁。 谷歌CEO 劈柴…

NVM的下载安装和使用

node包管理工具NVM让我们更加方便在各个node版本之间切换来适配不同的项目 一、下载安装 下载地址&#xff1a;github下载地址 https://github.com/coreybutler/nvm-windows/releases安装一直点下一步就行&#xff0c;可以安装在D、E盘都行&#xff0c;安装后检查是否安装成功…

“身份验证失败” authentication failed报错的原因

问题描述 问题出在target “send_emai” 的password属性&#xff0c;我们认为输入的是邮箱的密码&#xff0c;即使是给出正确的密码仍报错的情况下&#xff0c;还是让大家输入正确的密码。结果呢&#xff1f; 这里的“password”输入的并不是密码&#xff0c;而是一种授权码&…

Servlet开发-session和cookie理解案例-登录页面

项目展示 进入登录页面&#xff0c;输入正确的用户名和密码以后会自动跳到主页 登录成功以后打印用户名以及上次登录的时间&#xff0c;如果浏览器和客户端都保存有上次登录的信息&#xff0c;则不需要登录就可以进入主页 编码思路 1.首先提供一个登录的前端页面&…

使用MySQL聚合函数来聚合数据,结果发现有刺客...

问题&#xff1a; 使用MySQL聚合函数 group_concat 的坑&#xff01; 现象&#xff1a; 我有个业务&#xff0c;需要将表中符合条件的数据行的id聚合成一个字符串&#xff0c;以供另外一张表的查询过滤。 SELECTx FROMt_A WHEREFIND_IN_SET(guan_lian,(SELECTgroup_concat( i…

毫米波V2I网络的链路层仿真研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

工时管理系统,一款灵活性强、轻量级工时记录和管理工具

一、开源项目简介 无鱼工时管理系统&#xff0c;是一款轻量级工时记录和管理工具&#xff0c;包括项目管理&#xff0c;工时上报&#xff0c;工时日报&#xff0c;工时统计等功能。 无鱼工时管理系统可通过员工工时上报的方式&#xff0c;来记录项目所花费的工时&#xff0c;…

分享74个Java源代码总有一个是你想要的

分享74个Java源代码总有一个是你想要的 链接&#xff1a;https://pan.baidu.com/s/1DfGiAF7Ipde-SKeHZJ7-jQ?pwd8888 提取码&#xff1a;8888 项目名称 Akaxin v0.5.4 B2C网站管理系统购物网 v1.5 B3LOG Solo v1.0.0 for MySQL belog博客程序 v1.1 CKFinder 文件管理器…

创建视图权限问题ora1031,ora1720

Ora-1031 使用sql查询无问题&#xff0c;创建视图告警ora-1031 根据文档Document 271587.1 递归对象权限中角色收回时&#xff0c;会造成权限断档 解决方法&#xff1a; 对该对象进行授权&#xff08;尽量属主用户&#xff09; Grant select on interface.Material_view_pa…

字符检测专题第二期:通用、简单、快速,见证AI字符识别的超能力!

随着科技的不断进步&#xff0c;OCR&#xff08;光学字符识别&#xff09;技术在工业应用中扮演着越来越重要的角色。 在实际生产中&#xff0c;OCR技术可在生产流程监控、自动化设备控制、品质控制和物流控制等方面发挥作用&#xff0c;提高生产流水线的产量和质量&#xff0c…

基于Android的学生考勤签到请假管理系统+全套文档+全套视频教程

【项目功能介绍】 功能列表: 本系统包含后台管理和前端app双端系统, 本系统包含三个角色: 管理员,老师,学生。后台管理员的功能包含: 登录, 退出, ,通知管理,课程管理,课表管理,请假管理,用户管理; app端功能, 老师功能: 登录&#xff0c;退出, 注册, 日历控制日期展示, 查看不…