前端性能优化-Table渲染速度优化

教务系统-排课页面性能优化总结

一、前言

在公司教务系统中,排课页面慢的令人发指,在某些情况由于数据量大导致页面主进程卡死,遂组织进行一次排查优化,现记录一下

二、效果对比

以下数据均为UAT环境

Performence对比

更改前: 主进程渲染时间为 8s

教务系统-排课页面性能优化总结

标题:教务系统排课页面性能优化总结报告

一、前言

随着学校信息化建设的不断推进,教务系统的稳定性和效率直接影响到学校的教学管理工作。其中,排课功能作为教务系统的核心模块,其页面性能直接关系到教务人员的工作效率及用户体验。近期,我们对教务系统排课页面进行了深度的性能优化工作,现将相关优化过程和成果进行总结。

二、效果对比

以下数据均为UAT环境

Performence对比

更改前: 主进程渲染时间为 8s

更改后: 主进程渲染时间为 1s

三、方案总结

  1. 更换高性能表格插件  vxe-table 插件文档vxe-table v4 此步可提高80%渲染速度,如果时间紧张只看到此即可
  2. 优化算法,去循环减少时间复杂度具体如何参考下文
  3. 优化整理代码提高代码可读性

四、性能问题分析

经performance分析

费时的是vue3 中的diff 算法在不断地进行 patch函数

拉长时间线我们可以看到这三个函数导致 vue3 diff算法 的比较

coursePlanScheduList()                                       

createTableData()                                               

createDateTableRow()                                        

分析可知 在 此处 在createDateTableRow中有一个 O(n)3的循环 遂 打印各部分渲染时间可得知下图:

打印结果为:

四、优化措施实施

框架引擎更换

由上图我们可知在赋值的时候花费时间最多所以我们优先解决此问题, 本项目使用的框架是arco-design,找寻源码可知在框架源码中大量的使用了 ref,computed 从而导致了数据稍有改变就会触发vue中的diff 算法,table源码举证:

在vue3文档中toRefs是这么写的

toRefs()

将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。每个单独的 ref 都是使用  创建的。

响应式 API:工具函数 | Vue.js

arco-design, Table源码:

综上所述在arco-table 中table 的源码写的对于性能优化做的并不好,从而引出我们的"主角" vxe-table

只替换插件相同样本数据情况下性能表现如下:

算法优化

其实本该到这里在性能优化上已经很不错了,但是 我们前面说过有个O(n)3 的循环这里我们也顺手统计了一下时间

循环时间为 26ms

所以顺手优化了一下 利用空间换时间的算法 在后端老师的配合下,拆解成如下所示

  1. 后端老师返回A接口获取 机构校区下所有班级用于前端组成 表格的 head
  2. 后端老师返回B接口 按班级,日期:{ List<科目>},前端用于填充表格数据

服务端已Map 的方式返回(避免后端老师循环处理数据)增加接口响应速度,前端可以利用Map 的键值对来处理

服务端A接口 返回如下:

前端处理如下:

/*** 班级数据转换列* @param data 班级数据* @returns 列数据*/getColumnData(data: any): TableColumn[] {console.time('column');this.flatColumn = [];const dateColumn = new TableColumn().setTitle('日期').setField('date').setFixed('left').setWidth(140).setSlots({header: 'name_header',default: 'date',});const columns: TableColumn[] = [dateColumn];Object.keys(data).forEach((key: string) => {const campusAreaArr = key.split(',');const obj = { campusAreaName: campusAreaArr[1], campusAreaId: campusAreaArr[0] };const column = new TableColumn().setData(obj);this.campusAreaMap.set(obj.campusAreaId, column);columns.push(column);// 联合所有children 避免深度遍历this.flatColumn = this.flatColumn.concat(data[key]);});this.flatColumn.forEach((item: any) => {const campusObj = this.campusAreaMap.get(item.campusAreaId);const child = new ColumnChild().setData(item);this.setTemepplateObj(child.field);campusObj.addChildren(child);});this.setTemepplateObj('date');console.timeEnd('column');return columns;}

利用flatCloumn[] 数组来暂存处理数据

服务端B接口返回:

前端处理如下:

/***  整理行数据* @param startDateString 起始时间* @param endDateString 结束时间* @param temeplate 模板对象* @param result 循环数据* @returns {flatArr: 拍平数据, data: 表格数据}*/getTableRowData(startDateString: string, endDateString: string, temeplate: any, result: any) {// 日期循环开辟数组空间缓存矩阵const dataArr: any[] = [];let currentDate = startDateString;while (!dayjs(currentDate).isAfter(endDateString)) {// 浅拷贝模板对象const obj = { ...temeplate };obj.timestamp = new Date(currentDate).getTime();obj.date = dayjs(currentDate).format('YYYY-MM-DD');obj.dateStr = `${currentDate.substring(5)}(星期${this.dayOfWeekArr[dayjs(currentDate).day()]})`;dataArr.push(obj);currentDate = dayjs(currentDate).add(1, 'day').format('YYYY-MM-DD');}let flatData: any[] = [];Object.keys(result).forEach((key: string) => {const classDateObj = {timestamp: new Date(key.split(',')[1]).getTime(),classId: 'class_' + key.split(',')[0],};const obj = dataArr.find((item) => item.timestamp === classDateObj.timestamp);if (obj) {obj[classDateObj.classId] = result[key];}flatData = flatData.concat(result[key]);});return {flatData,data: dataArr,};}

这样我们只有一个O(n)2的循环查找,另为了优化大数据 矩阵[M*N] 的情况下 我们先用 while循环开辟内存中的数组空间,便于后面放入数组地址改变即可,多说无意,我们看一下我们优化后速度结果

循环有效减少了 50%时间

其他优化:

  1. 减少ref 使用shallowRef 替换 (减少 vue3深层数组响应式的监控)
  2. 使用 Promse.all 异步变同步处理事件
  3. 使用部分设计模式优化整体代码结构例如:
    1. 判断课程状态使用策略模式替换 原有 If/else
    2. 建造者模式方便属性赋值及扩展
    3. 组合模式组合列及子列
    4. 等等(详见代码)

五、优化效果验证

经过上述一系列性能优化措施后,排课页面的加载时间大幅缩短,用户操作流畅性显著提高,具体表现为:

  1. 页面首次加载速度提高了约80%;
  2. 排课操作响应时间平均缩短了50%; 原因:开启虚拟dom(结果取决于个电脑)
  3. 在高峰期并发访问情况下,系统整体稳定性增强,无明显卡顿现象。

最终前端打印速度在同数据情况下约为    40 ms 左右 (结果取决于个人电脑)

六、结语

本次教务系统排课页面性能优化工作取得显著成效,有效提升了系统的实际应用价值。我们将持续关注用户反馈,进一步挖掘潜在性能问题,不断提升教务系统的整体性能和用户体验,为学校的教学管理工作提供更高效、更稳定的支撑平台。

附录:

文档地址及参考文献:

vuejs 文档地址:

响应式 API:工具函数 | Vue.js

arco-design 文档地址:

三方应用: https://arco.design/vue/docs/start

vxe-table 文档地址:

vxe-table v4

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

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

相关文章

MHA的实验部署

一、前期准备 准备四台虚拟机&#xff0c;一台主服务器&#xff0c;一台管理服务器&#xff0c;两台从服务器 在开始之前先要关闭所有服务器的防火墙&#xff0c;以免有一些麻烦 二、实际操作 2.1 配置主服务器 2.2 配置从服务器1和2 2.3 给主从服务器实现软链接 2.4 配置mysql…

TypseScript再学习之类型别名和接口(10)

先看类型别名&#xff1a;使用关键字 type 声明,注意有等于号额 // 类型别名 使用关键字 type 声明,注意有等于号额 type Cat {name: string; }; let huahua: Cat {name: "花花", };type和interface不同之处在于&#xff1a;interface 是可以自动合并类型的&#…

【单片机 5.3开关检测】

文章目录 前言一、5.3开关检测1.1没按键按下的1.2有按键按下的 二、改进1.改进 三、独立键盘3.1为什么要取反3.2 实用的按键 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 课程需要&#xff1a; 提示&#xff1a;以下是本篇文章正文内容&#xf…

春暖助学 梦想启航

&#xff08;通讯员&#xff1a;赵灿飞 图&#xff1a;杨美、孙红浪&#xff09; 春风拂面暖阳斜&#xff0c;爱心助学谱华章。为弘扬中华民族传统美德&#xff0c;动员社会力量&#xff0c;传播社会爱心&#xff0c;缓解宁乡西部特殊家庭学子学业面临的实际困难&#xff…

CorePoolExecutor夺命连环问?看你可以接受几招?

一、前言 今天我在看why技术的时候&#xff0c;看到了这个。发现这个没有全部的八股回答&#xff1f;于是我就结合自己的经验&#xff0c;分享下八股 二、八股问答 2.1了解JDK Executors线程池吗? Executor就是一个线程池框架&#xff0c;在开发中如果需要创建线程可优先考…

JMeter自定义日志与日志分析

1 JMeter日志概览 JMeter与Java程序一样&#xff0c;会记录事件日志&#xff0c;日志文件保存在bin目录中&#xff0c;名称为jmeter.log。当然&#xff0c;我们也可以在面板中直接察看日志&#xff0c;点击右上角黄色标志物可以打开日志面板&#xff0c;再次点击收起。 可见&…

从入门到实战:vue3路由知识点

本人在B站上关于vue3的尚硅谷的课程&#xff0c;以下是整理一些笔记。 1.两个知识点 1.路由组件通常存放在pages 或 views文件夹&#xff0c;一般组件通常存放在components文件夹。 组件可以分为&#xff1a; 1. 一般组件&#xff1a;亲手写标签出来的 2. 路由组件&#…

非关系型数据库——Redis配置与优化

目录 一、关系型数据库和非关系型数据库 1.定义 1.1关系型数据库 1.2非关系型数据库 2.非关系型数据库产生的背景 3.关系型数据库和非关系型数据库区别 3.1适用性不同 3.2数据一致性要求不同 3.3数据模型不同 3.4数据查询语言不同 3.5数据存储方式不同 3.6扩展方式…

用Servlet实现一个简单的表白墙

1. 准备工作 创建项目,引入依赖...... 将静态页面放到项目中(放在webapp目录下): 当前,这个表白墙页面,已经可以输入内容,点击提交之后也能显示内容,后续后端要做的工作即: ①存档 用户点提交的时候,把刚才输入的内容通过网络传输给服务器,由服务器保存这个数据. ②读档 …

[中级]软考_软件设计_计算机组成与体系结构_04_寻址地址

寻址地址 概念指令的概念 寻址方式立即寻址方式直接寻址方式间接寻址方式寄存器寻址方式寄存器间接寻址方式往年真题 概念 指令的概念 一条指令就是机器语言的一个语句&#xff0c;它是一组有意义的二进制代码&#xff0c;指令的基本格式如下&#xff1a; 操作码字段地址码字…

基于springboot实现企业客户管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现企业客户管理系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个企业客户管理系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述企…

鸿蒙HarmonyOS应用开发之Node-API支持的数据类型和接口

Node-API的数据类型 napi_status 是一个枚举数据类型&#xff0c;表示Node-API接口返回的状态信息。 每当调用一个Node-API函数&#xff0c;都会返回该值&#xff0c;表示操作成功与否的相关信息。 typedef enum {napi_ok,napi_invalid_arg,napi_object_expected,napi_stri…

计算机网络面试问题(一)

1.在浏览器中输⼊URL并按下回⻋之后会发⽣什么 2.TCP三次握⼿的过程,为什么三次握手 TCP&#xff08;传输控制协议&#xff09;的三次握⼿是建⽴⽹络连接的过程&#xff0c;确保通信双⽅能够正确地进⾏数据传输。 第⼀次握⼿&#xff08;SYN&#xff09;&#xff1a; 客户端&am…

Php_Code_challenge13

题目&#xff1a; 答案&#xff1a; 解析&#xff1a; 开启一个会话&#xff0c;在SESSION变量"nums"为空时则对"nums","time","whoami"进行赋值&#xff0c;并在120秒后关闭会话&#xff0c;创建一个变量"$value"…

第6章 数据存储操作

思维导图 6.1 引言 数据存储与操作包括对存储数据的设计、实施和支持&#xff0c;最大化实现数据资源的价值&#xff0c;贯穿于数据创建/获取到处置的整个生命周期。 6.1.1 业务驱动因素 数据存储与操作活动对于依赖数据的企业来说非常关键&#xff0c;这些活动的主要驱动因素是…

Meta Pixel:助你实现高效地Facebook广告追踪

Meta Pixel 像素代码是用來衡量Facebook广告效果的一个官方数据工具&#xff0c;只要商家有在Facebook上投放广告就需要串联Meta Pixel 像素代码来查看相关数据。 它本质上是一段 JavaScript 代码&#xff0c;安装后可以让用户在自己网站上查看到访客活动。它的工作原理是加载…

记windows配置maven环境变量

配置环境变量 idea中配置maven

C++教学——从入门到精通 4.setw()语句

这次玩点新鲜的------setw() 这家虎是啥呢&#xff1f; 我们编程输出的时候总是要输出空格&#xff0c;但有些时候又点的手都麻了 这时setw语句就派上用场了 具体怎么用呢&#xff1f; 如下图 #include"iostream"// #include"iomanip"// bits/stdc…

AI智能写作:巧用AI大模型让新媒体变现插上翅膀【文末送书】

文章目录 一、AI智能写作的崛起二、AI智能写作与新媒体变现AI智能写作的挑战与应对策略 AI智能写作&#xff1a;巧用AI大模型让新媒体变现插上翅膀【文末送书】 近年来&#xff0c;人工智能&#xff08;AI&#xff09;技术的发展日新月异&#xff0c;逐渐渗透到了各行各业&…

稻盛和夫|普通人如何才能取得非凡成就?

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 稻盛和夫老先生曾经回答过这么一个问题&#xff1a; 资质平庸的普通人如何才能取得非凡的成就&#xff1f; 稻盛和夫认为&#xff1a;人生成就能力努力态度。 也就是&#xff1a;做一个努力工作却不甘于只做眼前的事&a…