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

news2024/11/23 11:38:28

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

一、前言

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

二、效果对比

以下数据均为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.coloradmin.cn/o/1562209.html

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

相关文章

SpringBoot+uniApp宠物领养小程序系统 附带详细运行指导视频

文章目录 一、项目演示二、项目介绍三、运行截图四、主要代码1.保存宠物信息代码2.提交订单信息代码3.查询评论信息代码 一、项目演示 项目演示地址&#xff1a; 视频地址 二、项目介绍 项目描述&#xff1a;这是一个基于SpringBootuniApp框架开发的宠物领养微信小程序系统。…

wps 开发插件

官方文档参考wps官方文档参考 1.环境安装 安装wps https://www.wps.cn/ 安装Node.js https://nodejs.org/en 安装代码编辑器 Visual Studio Code https://code.visualstudio.com/ 环境检查-进入cmd查看 node -v2.demo 2.1 demo下载 打开vscode&#xff0c;新建终端 安装…

渗透测试练习题解析 5(CTF web)

1、[安洵杯 2019]easy_serialize_php 1 考点&#xff1a;PHP 反序列化逃逸 变量覆盖 【代码审计】 通过 GET 的方式获取参数 f 的值&#xff0c;传递给变量 function 定义一个过滤函数&#xff0c;过滤掉特定字符&#xff08;用空字符替换&#xff09; 下面的代码其实没什么用…

面试智力题

面试智力题 二进位bit1. 题目&#xff1a;一千杯水&#xff0c;一杯水有毒&#xff0c;怎么用10只老鼠&#xff0c;把这杯水找出来&#xff08;1&#xff09;解法1&#xff1a;常规法&#xff08;2&#xff09;bit法&#xff08;位数法&#xff09; (3) 时间法三级目录 二进位b…

Flutter Web 的未来,Wasm Native 即将到来

早在去年 Google I/O 发布 Flutter 3.10 的时候就提到过&#xff0c; Flutter Web 的未来会是 Wasm Native &#xff0c;当时 Flutter 团队就表示&#xff0c;Flutter Web 的定位不是设计为通用 Web 的框架&#xff0c;类似的 Web 框架现在有很多&#xff0c;而 Flutter 的定位…

Vision-Language Models for Vision Tasks: A Survey

论文地址&#xff1a;https://arxiv.org/pdf/2304.00685.pdf 项目地址&#xff1a;https://github.com/jingyi0000/VLM_survey 一、综述动机 视觉语言模型&#xff0c;如CLIP&#xff0c;以其独特的训练方式显著简化了视觉识别任务的流程。它减少了对大量精细标注数据的依赖&a…

文生图大模型三部曲:DDPM、LDM、SD 详细讲解!

1、引言 跨模态大模型是指能够在不同感官模态(如视觉、语言、音频等)之间进行信息转换的大规模语言模型。当前图文跨模态大模型主要有&#xff1a; 文生图大模型&#xff1a;如 Stable Diffusion系列、DALL-E系列、Imagen等 图文匹配大模型&#xff1a;如CLIP、Chinese CLIP、…

Rust---有关介绍

目录 Rust---有关介绍变量的操作Rust 数值库&#xff1a;num某些基础数据类型序列(Range)字符类型单元类型 发散函数表达式&#xff08;&#xff01; 语句&#xff09; Rust—有关介绍 得益于各种零开销抽象、深入到底层的优化潜力、优质的标准库和第三方库实现&#xff0c;Ru…

Unity中UI系统1——GUI

介绍 工作原理和主要作用 基本控件 a.文本和按钮控件 练习&#xff1a; b.多选框和单选框 练习&#xff1a; 用的是第三种方法 c.输入框和拖动框 练习&#xff1a; 练习二&#xff1a; e.图片绘制和框 练习&#xff1a; 复合控件 a.工具栏和选择网格 练习&#xff1a; b.滚动视…

关于OcenaBase v4.2中,分区转移和负载均衡的技术解读

OceanBase​​​​​​​​​​​​​​作为一款原生分布式数据库&#xff0c;其核心的技术特性之一是高可扩展性&#xff0c;其具体表现在两个方面&#xff1a; 首先&#xff0c;是灵活的扩缩容能力&#xff0c;包括垂直扩缩容和水平扩缩容&#xff1a; 垂直扩缩容&#xff…

android APP monkey 测试

monkey 测试 一、电脑ADB安装及使用详解1、什么是 Monkey 测试2、什么是ADB3、ADB的作用4、安装前提条件5、ADB下载6、ADB安装与配置 二、连接安卓手机检查是否连接上安卓手机windows端安装ADB驱动 三、 monkey测试操作指令演示指令APP包名查看方式测试效果 一、电脑ADB安装及使…

蜜罐技术---德迅猎鹰

什么是蜜罐 蜜罐是一种互联网安全系统&#xff0c;部署诱饵和陷阱在关键网络入口&#xff0c;诱导攻击者攻击伪装目标&#xff0c;保护真实资产&#xff0c;并且对攻击者做行为取证和追踪溯源&#xff0c;定位攻击者自然人身份&#xff0c;提升主动防御能力&#xff0c;让安全…

Ps:阈值

阈值 Threshold命令可将灰度图像或彩色图像转换为仅包含黑色和白色的二值图像。 Ps菜单&#xff1a;图像/调整/阈值 Adjustments/Threshold Ps菜单&#xff1a;图层/新建调整图层/阈值 New Adjustment Layer/Threshold 阈值命令通过设置一个特定的亮度阈值&#xff08;阈值色阶…

EasyCVR视频汇聚平台海康Ehome2.0与5.0设备接入时的配置区别

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

ZCMU操作系统课程实验 - 实验1-Linux的使用

登录 1. 打开这个东西 2. 在 文件 - > 打开 中打卡机房里VMOS文件里的这个东东 3. 然后依次操作下去好了&#xff0c;有红色的选项&#xff0c;我都是选的"Do nothing"。完成后就会出现这样一个黑框框。 4. 让你登录。输入&#xff1a;root。密码&…

第十七章 Kafka

一、特性 - 高吞吐、低延迟 - 高伸缩性 - 持久性、可靠性 - 容错性 - 高并发 通过 O(1)的磁盘数据结构提供消息的持久化&#xff0c;这种结构对于即使数以 TB 的消息存储也能够保持长时间的稳定性能。 高吞吐量&#xff1a;即使是非常普通的硬件 Kafka 也可以支持每秒数百…

MSOX3104T是德科技MSOX3104T示波器

181/2461/8938产品概述&#xff1a; Keysight MSOX3104T X 系列示波器提供您更快获得测量见解所需的所有性能和功能&#xff0c;再次重新定义了您对通用示波器的期望。除了触摸的优点外&#xff0c;内置 USB 主机和 USB 设备端口还使 PC 连接变得容易。InfiniiVision MSOX3104…

Nginx 日志输出配置json格式

nginx日志输出配置json格式 nginx服务器日志相关指令主要有两条&#xff1a; (1) 一条是log_format&#xff0c;用来设置日志格式 (2) 另外一条是access_log&#xff0c;用来指定日志文件的存放路径、格式和缓存大小。 log_format指令用来设置日志的记录格式&#xff0c;它的语…

【面试八股总结】传输控制协议TCP(一)

一、什么是TCP协议 TCP是传输控制协议Transmission Control Protocol TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。 面向连接的&#xff1a;每条TCP连接杜只能有两个端点&#xff0c;每一条TCP连接只能是点对点的&#xff08;一对一&#xff09;可靠的&#xff1a…

iPhone设备中如何分析和解决应用程序崩溃日志的问题

​ 目录 如何在iPhone设备中查看崩溃日志 摘要 引言 导致iPhone设备崩溃的主要原因是什么&#xff1f; 使用克魔助手查看iPhone设备中的崩溃日志 奔溃日志分析 总结 摘要 本文介绍了如何在iPhone设备中查看崩溃日志&#xff0c;以便调查崩溃的原因。我们将展示三种不同的…