前端性能优化 - 虚拟滚动
一 需求背景
需求:在一个表格里面一次性渲染全部数据,不采用分页形式,每行数据都有Echart图插入。
问题:图表渲染卡顿
技术栈:Vue、Element UI
卡顿原因:页面渲染时大量的元素参与到了重排的动作中,性能差
优化方案:虚拟滚动
二 虚拟滚动原理
虚拟滚动其实就是综合数据分页和无限滚动的方法,在有限的视口中只渲染我们所能看到的数据,超出视口之外的数据就不进行渲染,可以通过计算可视范围内的单元格,保证每一次滚动渲染的DOM元素都是可以控制的,不会担心像数据分页一样一次性渲染过多,也不会发生像无限滚动方案那样会存在数据堆积,是一种很好的解决办法。
假设实际开发中服务端一次响应20万条列表数据,此时设备屏幕只允许容纳20条,那么用户理论上只可以看见20条数据,其他的数据不会进行渲染加载。如果前端将20万条数据全部渲染成DOM元素,可能造成程序卡顿,占用较大资源,非常影响用户体验,那么虚拟滚动技术就完美的解决了这一问题。

可以计算:卷入行数 = scrollTop(卷入高度) / 每行的高度(itemH)
如何计算可视区域渲染的元素以及实现虚拟滚动,步骤如下:
- 统一设置每一行的
高度需要相同,方便计算。 - 需要计算渲染数据数量(数组的长度),根据每行的高度以及元素的总量计算整个DOM渲染容器的高度。
- 获取可视区域的高度
- 触发滚动事件后,计算偏移量(滚动条据顶距离),再根据可视区域高度计算本次偏移的截止量,得到需要渲染的具体数据。
- 对于与表格的列来说,需要做虚拟滚动的话,在x轴同样可以根据以上步骤执行,实现横向虚拟滚动。
三 项目具体代码:
<el-tableref="latestPositionRef"v-loading="tableLoading"class="table-fixed"size="mini":data="sliceTable"height="355px":cell-style="cellStyle"row-key="secId"@sort-change="handleSortChange"@selection-change="handleSelectionChange"><el-table-column type="selection" width="55" align="center" :reserve-selection="true" /><el-table-column label="排名" width="50px" align="center" fixed><template slot-scope="scope">{{ scope.$index + 1 }}</template></el-table-column><DynamicColumnv-for="(ite, index) in overviewColumns":key="index":item="ite":empty="1":data-list="infoList"table-sign="latest-position-list":schemas="overviewColumns"@changeColumn="(cols)=>{overviewColumns=cols;}"/><el-table-column label="备注设置" align="center" width="50" fixed="right"><template slot-scope="scope"><el-buttonv-if="scope.row.secId"type="text"size="mini"plain@click="setRemark(scope.row)">查看</el-button></template></el-table-column></el-table>
data() {return {// 动态列-ETF精选overviewColumns: this.$columns.getColumns('etf_selected_list'),// 表格数据infoList: [],showInfoList: [],// 开始索引startIndex: 0,// 空元素,用于撑开table的高度vEle: undefined,// 每一行高度itemHeight: 42,}
}
watch: {sliceTable: {handler() {// 解决表格错位问题this.$nextTick(() => {this.$refs.latestPositionRef.doLayout()})},deep: true},
}
async created() {// 创建一个空元素,这个空元素用来撑开 table 的高度,模拟所有数据的高度this.vEle = document.createElement('div')},
computed: {// 这个是截取表格中的部分数据,放到了 table 组件中来显示sliceTable() {return this.showInfoList.slice(this.startIndex, this.startIndex + 6)},}
/** 加载ETF精选列表数据 */loadData() {console.log('loadData')const start_i = this.showInfoList.lengthfor (let i = start_i; i < start_i + 10; i++) {this.showInfoList.push(this.infoList[i])}this.$nextTick(() => {// 设置成绝对定位,这个元素需要我们去控制滚动this.$refs.latestPositionRef.$el.querySelector('.el-table__body').style.position = 'absolute'// 计算表格所有数据所占内容的高度this.vEle.style.height =this.showInfoList.length * this.itemHeight + 'px'// 把这个节点加到表格中去,用它来撑开表格的高度this.$refs.latestPositionRef.$el.querySelector('.el-table__body-wrapper').appendChild(this.vEle)// 重新设置曾经被选中的数据this.selection.forEach((row) => {this.$refs.latestPositionRef.toggleRowSelection(row, true)})})},tableScroll() {console.log('tableScroll')const bodyWrapperEle = this.$refs.latestPositionRef.$el.querySelector('.el-table__body-wrapper')console.log(bodyWrapperEle, 'bodyWrapperEle')// 滚动的高度const scrollTop = bodyWrapperEle.scrollTop// 下一次开始的索引this.startIndex = Math.floor(scrollTop / this.itemHeight)// 滚动操作bodyWrapperEle.querySelector('.el-table__body').style.transform = `translateY(${this.startIndex * this.itemHeight}px)`// 滚动操作后,上面的一些 tr 没有了,所以需要重新设置曾经被选中的数据this.selection.forEach((row) => {this.$refs.latestPositionRef.toggleRowSelection(row, true)})// 滚动到底,加载新数据if (bodyWrapperEle.scrollHeight <=scrollTop + bodyWrapperEle.clientHeight) {if (this.showInfoList.length === this.infoList.length) {this.$message.warning('没有更多了')return}this.loadData()// 解决el-table中内容错位// this.$nextTick(() => {// this.$refs.latestPositionRef.doLayout()// })}}
四 其他方案:
分段渲染、数据分页、无限滚动
学习:https://www.modb.pro/db/122781
相关文章:
前端性能优化 - 虚拟滚动
一 需求背景 需求:在一个表格里面一次性渲染全部数据,不采用分页形式,每行数据都有Echart图插入。 问题:图表渲染卡顿 技术栈:Vue、Element UI 卡顿原因:页面渲染时大量的元素参与到了重排的动作中&#x…...
手写 Promise(1)核心功能的实现
一:什么是 Promise Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。 Promise对象有以下两个特点。 (1)对象的状态不受…...
深入探究Java内存模型
文章目录 🌟 Java虚拟机内存模型🍊 一、方法区🍊 二、堆🎉 堆的基本概念🎉 堆的结构📝 新生代📝 老年代 🎉 堆的分配策略📝 对象优先分配📝 空间优先分配 &am…...
深度学习 | Pytorch深度学习实践 (Chapter 10、11 CNN)
十、CNN 卷积神经网络 基础篇 首先引入 —— 二维卷积:卷积层保留原空间信息关键:判断输入输出的维度大小特征提取:卷积层、下采样分类器:全连接 引例:RGB图像(栅格图像) 首先,老师…...
谈谈你对spring boot 3.0的理解
谈谈你对spring boot 3.0的理解 一,Spring Boot 3.0 的兼容性 Spring Boot 3.0 在兼容性方面做出了很大的努力,以支持存量项目和老项目。尽管如此,仍需注意以下几点: Java 版本要求:Spring Boot 3.0 要求使用 Java 1…...
【大数据】Hadoop
文章目录 概述Hadoop组成HDFSMapReduce写MapReduce程序(Hadoop streaming) YARNHadoop 启动 工作方式Hadoop的主从工作方式Hadoop的守护进程 运行模式本地运行模式伪分布式运行模式完全分布式运行模式 Hadoop高可用的解决方案ZooKeeper quorumZKFC 环境搭…...
Spring实例化源码解析之Bean的实例化(十二)
前言 本章开始分析finishBeanFactoryInitialization(beanFactory)方法,直译过来就是完成Bean工厂的初始化,这中间就是非lazy单例Bean的实例化流程。ConversionService在第十章已经提前分析了。重点就是最后一句,我们的bean实例化分析就从这里…...
git常用的几条命令介绍
必须了解的命令整理 1,git init 初始化一个新的Git仓库。 这将在当前目录中创建一个名为".git"的子目录,Git会将所有仓库的元数据存储在其中。 2,git clone 克隆一个已存在的仓库。 这会创建一个本地仓库的副本,包…...
使用VisualSVN在Windows系统上设置SVN服务器,并结合内网穿透实现公网访问
文章目录 前言1. VisualSVN安装与配置2. VisualSVN Server管理界面配置3. 安装cpolar内网穿透3.1 注册账号3.2 下载cpolar客户端3.3 登录cpolar web ui管理界面3.4 创建公网地址 4. 固定公网地址访问 前言 SVN 是 subversion 的缩写,是一个开放源代码的版本控制系统…...
第18章 SpringCloud生态(三)
18.21 Nacos能存储什么样格式的数据(配置中心) 难度:★ 重点:★ 白话解析 看下面这副Nacos控制台的截图就明白了 参考答案 六种格式数据:Text、JSON、XML、Yaml、HTML和Properties格式。 18.22 Nacos是如何实现配置动态更新的(配置中心) 难度:★★ 重点:★★★ 白话…...
leetcode:2347. 最好的扑克手牌(python3解法)
难度:简单 给你一个整数数组 ranks 和一个字符数组 suit 。你有 5 张扑克牌,第 i 张牌大小为 ranks[i] ,花色为 suits[i] 。 下述是从好到坏你可能持有的 手牌类型 : "Flush":同花,五张相同花色的…...
2007-2022 年上市公司国内外专利授权情况数据
2007-2022 年上市公司国内外专利授权情况 1、来源:国家知识产权局 2、时间:2007-2022 年 3、范围:上市公司 4、指标: 证券代码、年份、省份、城市、行业代码、授权地区、申请类型、专利、发明专利、实用新型、外观设计 5、…...
安全渗透测试网络基础知识之路由技术
#1.静态路由技术 ##1.1路由技术种类: 静态路由技术、动态路由技术 ##1.2静态路由原理 静态路由是网络中一种手动配置的路由方式,用于指定数据包在网络中的传输路径。与动态路由协议不同,静态路由需要管理员手动配置路由表,指定目的网络和下一跳路由器的关联关系。 比较适合…...
【大数据】Kafka 实战教程(二)
Kafka 实战教程(二) 1.下载2.安装3.配置4.运行4.1 启动 Zookeeper4.2 启动 Kafka 5.第一个消息5.1 创建一个 Topic5.2 创建一个消息消费者5.3 创建一个消息生产者 1.下载 你可以在 Kafka 官网:http://kafka.apache.org/downloads,…...
React 框架
1、React 框架简介 1.1、介绍 CS 与 BS结合:像 React,Vue 此类框架,转移了部分服务器的功能到客户端。将CS 和 BS 加以结合。客户端只用请求一次服务器,服务器就将所有js代码返回给客户端,所有交互类操作都不再依赖服…...
数据结构与算法之图: Leetcode 133. 克隆图 (Typescript版)
克隆图 https://leetcode.cn/problems/clone-graph/description/ 描述 给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。 图中的每个节点都包含它的值 val(int) 和其邻居的列表(list[No…...
illuminate/database 使用 一
illuminate/database 是完整的php数据库工具包,即ORM(Object-Relational Mapping)类库。 提供丰富的查询构造器,和多个驱动的服务。作为Laravel的数据库层使用,也可以单独使用。 一 使用 加载composer之后ÿ…...
前端koa搭建服务器(保姆级教程)——part1
目录 koa简介前端项目搭建koa环境第一步:新建项目第二步:环境初始化,安装依赖初始化项目,生成package.json文件安装koa依赖安装koa-router 路由管理依赖安装dotenv 环境变量依赖安装nodemon 热启动依赖 第三步:代码调用…...
js逆向第一课 密码学介绍
什么是密码学? 密码学(Cryptology)是一种用来混淆的技术,它希望将正常的、可识别的信息转变为无法识别的信息。 目前密码学的研究,一种是偏应用,把现有的,别人研究出来的密码学算法,放在一个合…...
Dynamic DataSource 多数据源配置【 Springboot + DataSource + MyBatis Plus + Druid】
一、前言 MybatisPlus多数据源配置主要解决的是多数据库连接和切换的问题。在一些大型应用中,由于数据量的增长或者业务模块的增多,可能需要访问多个数据库。这时,就需要配置多个数据源。 二、Springboot MyBatis Plus 数据源配置 2.1、单数…...
终极防休眠指南:Move Mouse免费工具完整使用教程
终极防休眠指南:Move Mouse免费工具完整使用教程 【免费下载链接】movemouse Move Mouse is a simple piece of software that is designed to simulate user activity. 项目地址: https://gitcode.com/gh_mirrors/mo/movemouse 你是否经常遇到这样的困扰&am…...
Agent-Sandbox UI 上线,来看看有哪些的功能是你经常使用的?韶
一、简化查询 1. 先看一下查询的例子 /// /// 账户获取服务 /// /// /// public class AccountGetService(AccountTable table, IShadowBuilder builder) {private readonly SqlSource _source new(builder.DataSource);private readonly IParamQuery _accountQuery build…...
go语言学习(基本数据类型)
布尔类型true false布尔型数据只有 true(真)和 false(假)两个值 布尔类型变量的默认值为falseGo 语言中不允许将整型强制转换为布尔型布尔型无法参与数值运算,也无法与其他类型进行转换 package mainimport "f…...
RAGAS 了解吗?它的评估指标有哪些?评估流程是怎样的?评估数据如何获取和构造?
1. 题目分析做过 RAG 项目的人大概都有过这种体验:系统搭完了,效果怎么样?说好也行,说不好也行,全凭主观感觉。你觉得检索结果挺相关的,老板觉得回答不够精准;你觉得答案已经很准了,…...
电源管理入门-18 Power Domain管理
SoC中通常有很多IP,按逻辑可以把几个相关功能的IP划为一个电源域。一个电源域内的IP,通常按相同的方式由同一个硬件模块PMIC供电,电压一样并且电源管理例如休眠唤醒一致。为什么有设备电源管理还需要power domain划分? 对每个设备…...
终极免费虚拟光驱指南:如何在Windows上轻松挂载ISO文件
终极免费虚拟光驱指南:如何在Windows上轻松挂载ISO文件 【免费下载链接】WinCDEmu 项目地址: https://gitcode.com/gh_mirrors/wi/WinCDEmu 在数字时代,我们不再需要物理光驱来读取光盘内容,但ISO、NRG、MDS等光盘映像文件仍然无处不…...
8款热门数据治理工具深度测评,哪款功能最强大?
业务要报表,数据散在 ERP、CRM、Excel 十几个系统里,跨部门取数要等好几天。好不容易凑齐数据,财务和业务口径不一致,核心指标算出来两个数。数据越多越混乱,找数据比用数据难,这些问题都是因为数据治理没做…...
八. 实战:CUDA-BEVFusion部署优化-从预处理到3D检测全流程解析
1. CUDA-BEVFusion部署优化全景解析 在自动驾驶感知系统中,BEVFusion作为多模态融合的标杆算法,其部署效率直接影响着车载计算单元的实时性表现。本次我们将深入CUDA-BEVFusion的完整部署流水线,从数据预处理到3D检测输出的每个环节ÿ…...
VINS-Mono代码架构深度解析:从feature_tracker到pose_graph,搞懂每个模块在做什么
VINS-Mono代码架构深度解析:从feature_tracker到pose_graph,搞懂每个模块在做什么 当你第一次成功运行VINS-Mono并看到实时轨迹在RVIZ中流畅呈现时,那种成就感不言而喻。但作为追求技术深度的开发者,我们不会满足于"能跑通&q…...
终极指南:R3nzSkin内存换肤技术的完整实现与实战进阶
终极指南:R3nzSkin内存换肤技术的完整实现与实战进阶 【免费下载链接】R3nzSkin Skin changer for League of Legends (LOL) 项目地址: https://gitcode.com/gh_mirrors/r3n/R3nzSkin 在游戏修改领域,内存换肤技术代表了逆向工程与实时内存操作的…...
