前端性能优化 - 虚拟滚动

一 需求背景

需求:在一个表格里面一次性渲染全部数据,不采用分页形式,每行数据都有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

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

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

相关文章

MySQL数据库(三)

文章目录 MySQL数据库一、约束条件二、约束条件之主键三、补充一些其它SQL语句四、表查找关键字Select与from五、查询关键字之where筛选六、查询关键字之group by分组七、分组补充函数八、关键字之having过滤九、关键字之distinct去重十、关键字之order by排序十一、关键字之li…

苹果开发者 Xcode发布TestFlight全流程

打包前注意事项 使用Xcode导出安装包之前&#xff0c;必须先确认账户的所有合约是否全部同意&#xff0c;如果有不同意的&#xff0c;在出包的时候会弹出报错 点击前往苹果开发者官网https://appstoreconnect.apple.com/agreements/ 登录自己的开发者账户后&#xff0c;可以看…

react项目实现文件预览,比如PDF、txt、word、Excel、ppt等常见文件(腾讯云cos)

使用腾讯云文档预览&#xff0c;需要开通文档预览功能&#xff0c;该功能需要收费的。 使用限制 如果需要图片预览、视频或音频可以使用获取下载链接。 页面代码 <button onClick() > {handleClick(myself/文档.xlsx)}>预览</button><div style{{ height:…

谈谈你对spring boot 3.0的理解

谈谈你对spring boot 3.0的理解 一&#xff0c;Spring Boot 3.0 的兼容性 Spring Boot 3.0 在兼容性方面做出了很大的努力&#xff0c;以支持存量项目和老项目。尽管如此&#xff0c;仍需注意以下几点&#xff1a; Java 版本要求&#xff1a;Spring Boot 3.0 要求使用 Java 1…

Boundary-Aware RGBD Salient Object Detection With Cross-Modal Feature Sampling

方法 体会 实验做得比较详细&#xff0c;但未公布代码

浏览器标签上添加icon图标;html引用ico文件

实例 <link rel"shortcut icon" href"./XXX.ico" type"image/x-icon">页面和图标在同一目录内 则 <link rel"shortcut icon" type"text/css" href"study.ico"/>可以阿里矢量图库关键字搜索下载自己…

H3C SecParh堡垒机 data_provider.php 远程命令执行漏洞

构造poc执行远程命令&#xff1a; /audit/data_provider.php?ds_y2019&ds_m04&ds_d02&ds_hour09&ds_min40&server_cond&service$(id)&identity_cond&query_typeall&formatjson&browsetrue漏洞证明&#xff1a; 文笔生疏&#xff0c…

windows开机自启动和忘记密码-备忘

windows开机自启动和忘记密码-备忘 文章目录 windows开机自启动和忘记密码-备忘1.自启动网址定时任务方式 2.忘记windows用户密码 1.自启动 网址 参考博文&#xff1a;https://blog.csdn.net/wwzmvp/article/details/113656544&#xff0c;感谢博主。 定时任务方式 如图&#…

小游戏外包开发流程及费用

小游戏的开发流程和费用会因项目的规模、复杂性和所选技术平台而有所不同。以下是一般的小游戏开发流程和可能的费用因素&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 开发流程&#xff1a; 概念和…

云原生微服务实战 Spring Cloud Alibaba 之 Nacos

系列文章目录 第一章 Java线程池技术应用 第二章 CountDownLatch和Semaphone的应用 第三章 Spring Cloud 简介 第四章 Spring Cloud Netflix 之 Eureka 第五章 Spring Cloud Netflix 之 Ribbon 第六章 Spring Cloud 之 OpenFeign 第七章 Spring Cloud 之 GateWay 第八章 Sprin…

ES 8.x 向量检索性能测试 把向量检索性能提升100倍!

向量检索不仅在的跨模态检索场景中应用广泛&#xff0c;随着chat gpt的或者&#xff0c;利用es的向量检索&#xff0c;在Ai领域发挥着越来越大的作用。 本文&#xff0c;主要测试es的向量检索性能。我从8.x就开始关注ES的向量检索了。当前ES已经发布到 8.10 版本。以下是官方文…

mybatis书写

mybatis <select id"selectUserList" resultType"map"> select * from user </select><!--根据主键查询一条--> <select id"selectById" resultType"map" parameterType"java.lang.Integer"> sele…

Tomcat及jdk安装下载及环境配置(超超超详解)

我是看了两篇博客安装配置好的 jdk 最详细jdk安装以及配置环境&#xff08;保姆级教程&#xff09;_安装jdk需要配置环境变量吗-CSDN博客 tomcat Tomcat的下载安装与配置及常见问题处理【Win11】 - 鞠雨童 - 博客园 (cnblogs.com) 本篇文章是我解决了很多朋友的tomcat配置问题总…

Spring MVC常用十大注解

Spring MVC常用十大注解 一&#xff0c;什么要使用注解 使用注解可以简化配置&#xff0c;提高代码的可读性和可维护性。通过注解可以实现依赖注入&#xff0c;减少手动管理对象的代码量。注解还支持面向切面编程&#xff0c;实现切面、切入点和通知等。此外&#xff0c;注解提…

数据可视化素材分享 | 数十图表、无数模板

很多人在后台求分享报表、源代码&#xff0c;其实何必这么麻烦&#xff0c;在奥威BI数据可视化平台上点击即可获得大量的可视化素材&#xff0c;如数十种可视化图表&#xff0c;适用于不同分析场景&#xff1b;又如大量不同主题的BI数据可视化报表模板&#xff0c;套用后替换数…

GoLong的学习之路(四)语法之循环语句

书接上回&#xff0c;上回说到运算符&#xff0c;这次我们说一个编程语言中最重要的一点&#xff1a;流程控制&#xff0c;及循环语句 文章目录 循环语句if else(分支结构)if条件判断特殊写法 for(循环结构)for range(键值循环) switch casegoto(跳转到指定标签)break(跳出循环…

按键中断控制LED灯亮灭

EXTI—外部中断/事件控制器 EXTI&#xff08;External interrupt/event controller&#xff09;—外部中断/事件控制器&#xff0c;管理了控制器的 20 个中断/事 件线。每个中断/事件线都对应有一个边沿检测器&#xff0c;可以实现输入信号的上升沿检测和下降沿的 检测。EXTI可…

【广州华锐互动】关于物理力学的3D实验实操平台

在科学的广阔领域中&#xff0c;物理力学是一个至关重要的分支&#xff0c;它探索了物体在力作用下的运动规律。然而&#xff0c;传统的物理实验往往需要复杂的设备和大量的操作&#xff0c;这对于学生来说是一项巨大的挑战。为了解决这个问题&#xff0c;广州华锐互动开发了物…

Hadoop3教程(三十五):(生产调优篇)HDFS小文件优化与MR集群简单压测

文章目录 &#xff08;168&#xff09;HDFS小文件优化方法&#xff08;169&#xff09;MapReduce集群压测参考文献 &#xff08;168&#xff09;HDFS小文件优化方法 小文件的弊端&#xff0c;之前也讲过&#xff0c;一是大量占用NameNode的空间&#xff0c;二是会使得寻址速度…

浅谈RabbitMQ的延迟队列

Part 01、 延迟队列是什么 延迟队列代表了一种强大的消息传递机制&#xff0c;允许我们在将消息发送至RabbitMQ时&#xff0c;规定它们只能在未来某个预定的时间点被消费。这种特殊类型的消息被简称为"延迟消息"。 以RabbitMQ为例&#xff0c;它允许我们通过延迟…