前端性能优化 - 虚拟滚动
一 需求背景
需求:在一个表格里面一次性渲染全部数据,不采用分页形式,每行数据都有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、单数…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
Redis上篇--知识点总结
Redis上篇–解析 本文大部分知识整理自网上,在正文结束后都会附上参考地址。如果想要深入或者详细学习可以通过文末链接跳转学习。 1. 基本介绍 Redis 是一个开源的、高性能的 内存键值数据库,Redis 的键值对中的 key 就是字符串对象,而 val…...
Android Framework预装traceroute执行文件到system/bin下
文章目录 Android SDK中寻找traceroute代码内置traceroute到SDK中traceroute参数说明-I 参数(使用 ICMP Echo 请求)-T 参数(使用 TCP SYN 包) 相关文章 Android SDK中寻找traceroute代码 设备使用的是Android 11,在/s…...
