性能优化 | el-table中内嵌大量el-input控件导致渲染卡顿的问题

news2024/12/25 10:28:17

场景

项目中有一个应用场景,用户需要在表单中大量使用选择框以及输入框填写数据(每一行大概有三十几个输入框),当选择框与输入框达到一定数量的时候,页面会出现输入不连续、卡顿的现象,如下图:
需求原型.png

排查

查了一下网上的解决方案,大体是因为页面渲染过多的el-input输入框给浏览器带来较大的渲染压力导致的。基于这点,对项目作出优化。

引入虚拟表格

虚拟表格,简单来说就是页面并不渲染表格中的所有数据,只渲染可视窗口部分的数据,当用户拖动滚动条滚动的时候,逐渐加载数据。这个适用于表格中需要渲染大量数据的场景,从而减轻浏览器的渲染压力。

对于elementui中使用el-table加入虚拟列表,可以参考下面这篇文章:
element全网最简单el-table实现虚拟列表

参考上面的文章,做了一个初版的效果。但由于虚拟列表只渲染部分数据的特性,所以一定会带来一个缺陷,那就是会短暂出现白屏的问题,即用户看到未渲染的区域。排查原因得知是因为el-table的占位区域append设置为定高totalHeight

<!-- 占位 -->
<template #append>
  <div :style="{ height: `${totalHeight}px` }"></div>
</template>

...
totalHeight() {
  return this.tableData.length * this.itemHeight
}

经过思考,改成动态变化的高度,从而形成一种滚动触底更新的效果:

// 改变append的高度
updated() {
  if (this.$refs.multipleTable) {
    const bodyEl = this.$refs.multipleTable.$el.getElementsByTagName("tbody")[0]
    if (bodyEl.offsetHeight) {
      this.totalHeight = bodyEl.offsetHeight
    } else if (bodyEl.offsetHeight === 0 && this.tableData.length === 0) {
      this.totalHeight = 0
    }
    // 重新绘制表格
    this.$refs.multipleTable.doLayout()
  }
},

虚拟表格再优化

引入虚拟表格后,加载确实快不少,输入卡顿的显现也明显优化。但发现一个问题,原有的选择方法不生效,当用户滚动的时候,原有的选择项被清空。那么,如何记录选择列表的状态呢?elementui提供了一个reserve-selection的API,用于记录列表项的选择状态:
reserve-selection.png

当然,也需要重写@select="handleSelect"@select-all="handleSelectAll"方法:

// 监听选择全部
handleSelectAll() {
  if (this.isSelectAll) {
    this.tableData.forEach(item => {
      this.$refs.multipleTable.toggleRowSelection(item, false)
    })
    this.selectList = []
    this.isSelectAll = false
  } else {
    this.tableData.forEach(item => {
      this.$refs.multipleTable.toggleRowSelection(item, true)
    })
    this.selectList = this.tableData
    this.isSelectAll = true
  }
},
// 手动触发选择事件
handleSelect(selection) {
  this.selectList = selection
  if (selection.length === this.tableData.length) {
    this.isSelectAll = true
  } else {
    this.isSelectAll = false
  }
},

引入虚拟输入框

引入虚拟列表后,效果确实提升了不少,至少在大数据量的情况下,不再会出现卡顿了(因为大数据量其实只渲染固定的数据)。但还有可以优化的空间吗?
我们之前提到,造成页面卡顿的原因,就是大量渲染了el-input以及el-select控件。那么,可以再进一步优化,以减少控件的渲染数量吗?我在这篇文章中找到了灵感:
vue大数据表格卡顿问题的完美解决方案
或者直接看文章提到的demo:
Demo
DEMO.png
核心思路就是,**只有当需要编辑的时候,才显示输入框,其余都显示内容。**这么一来,最多只会渲染1个编辑控件,卡顿问题可以进一步得到优化。

实现思路

  • template中根据条件选择渲染编辑控件,默认显示表格内容(同时通过修改样式模拟输入框必填标红);
  • 鼠标点击表格的时候,记录当前表格的坐标,用于切换编辑控件;
  • 页面根据渲染条件,切换编辑控件,同时自动聚焦到编辑框中。

示例代码如下所示:

<el-form-item :prop="'displayList.' + $index + '.出差地点'">
  <el-input v-if="focusCell === `${$index}-出差地点`" type="textarea" v-model="row['出差地点']" @blur="beforeComputedAll" autosize></el-input>
  <div v-else :class="row['出差地点'] ? 'm-input' : 'custom-required'">{{ row['出差地点'] }}</div>
</el-form-item>

记录表格坐标可以使用el-table的@cell-click方法:

// 聚焦单元格
updateFocusCell(row, col, cell) {
  if (this.focusDebounce) {
    clearTimeout(this.focusDebounce)
    this.focusDebounce = null
  }
  this.focusDebounce = setTimeout(() => {
    const lineNo = row['行号']
    const prop = col.property
    const idx = this.displayList.findIndex(item => item['行号'] === lineNo)
    if (this.focusCell !== `${idx}-${prop}`) {
      this.focusCell = `${idx}-${prop}`
      this.$nextTick(() => {
        target.focus()
      })
    }
    this.focusDebounce = null
  }, 20)
},

最终效果

最终效果.jpg

总结

至此,表格已经从一开始的输入卡顿,到现在基本是可以流畅输入了,使用体验得到大大的提升。当然还有优化的空间,比如校验逻辑的编写,以及一些相关的计算等等,那块就是属于算法层面的东西了,在此就不展开叙述。
对于表格大批量数据渲染的优化方案,总结如下:

  • 引入虚拟列表,只渲染可视化区域的数据;
  • 模拟编辑控件,仅在需要编辑的时候才展示;
  • 计算逻辑优化,减少计算时间。

第一次遇到这种类型的优化,觉得挺有意思的,在此做一个记录。如果大家有更好的优化方案也可以在评论区提出,欢迎大家一起学习~

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

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

相关文章

纯血鸿蒙APP实战开发——自定义视图实现Tab效果

介绍 本示例介绍使用Text、List等组件&#xff0c;添加点击事件onclick,动画&#xff0c;animationTo实现自定义Tab效果。 效果预览图 使用说明 点击页签进行切换&#xff0c;选中态页签字体放大加粗&#xff0c;颜色由灰变黑&#xff0c;起到强调作用&#xff0c;同时&…

FreeRTOS资源管理

1.以前临界资源的保护方式 有使用过静态局部变量来保护临界资源&#xff0c;也有用队列&#xff0c;信号量&#xff0c;互斥量来保护临界资源。这些都是在多个任务会共同使用临界资源的情况下我们的保护方式。 问题提出&#xff1a;如果有个传感器在读取数据时有严格的时序&a…

2路模拟音频光端机 JR-CA02

概述 JR-CA02光端机由发送机JR-CA02 Tansmitter和接收机JR-CA02 Receiver组成&#xff0c;通过一定距离长度的光纤相连接&#xff0c;传输2路Audio模拟音频&#xff08;即1路立体声&#xff09;。且每路音频分配输出。 JR-CA02光端机具有运行主要技术参数的监测功能&#xff…

Java的java.util.concurrent.ExecutorService简介

在Java并发编程的璀璨星空中&#xff0c;ExecutorService无疑是那颗最耀眼的明星。它不仅是Java并发编程的核心组件之一&#xff0c;更是构建高并发、高性能应用的秘密武器。今天&#xff0c;我们就来一场说走就走的探索之旅&#xff0c;揭开它的神秘面纱&#xff01; &#x1…

【高校科研前沿】中国科学院地理资源所钟帅副研究员研究组博士生朱屹东为一作在Top期刊发文:从潜力到利用:探索西藏风能资源开发的技术路径优化布局

01 文章简介 论文名称&#xff1a;From potential to utilization: Exploring the optimal layout with the technical path of wind resource development in Tibet&#xff08;从潜力到利用:探索西藏风能资源开发的技术路径优化布局&#xff09; 文章发表期刊&#xff1a;《…

盘一盘接口测试的那些痛点,你现在会解决了吗

前言 说到接口测试&#xff0c;想必大家一定不会陌生。接口测试就是测试系统组件间&#xff0c;接口对接是否顺畅的一种测试。包括测试数据能否交换、能否传递、能否正常控制管理过程&#xff0c;以及系统间的相互逻辑依赖关系&#xff0c;等等。 由于接口测试主要是检测系统…

MybatisPlus也能轻松生成三层架构代码?

&#x1f469;&#x1f3fd;‍&#x1f4bb;个人主页&#xff1a;阿木木AEcru &#x1f525; 系列专栏&#xff1a;《Docker容器化部署系列》 《Java每日面筋》 &#x1f4b9;每一次技术突破&#xff0c;都是对自我能力的挑战和超越。 目录 一、前言三层架构的流程图为什么使用…

2002-2021年各地区平均受教育年限数据(分性别)(含原始数据+计算过程+计算结果)

2002-2021年各地区平均受教育年限数据&#xff08;分性别&#xff09;&#xff08;含原始数据计算过程计算结果&#xff09; 1、时间&#xff1a;2002-2021年 2、来源&#xff1a;国家统计局、统计年鉴、各省年鉴 3、指标&#xff1a;行政区划代码、地区、年份、人均受教育年…

测试人员必用的10个Chrome扩展插件

背景&#xff1a;谷歌Chrome浏览器是全球所有测试人员最受欢迎和必备的浏览器之一&#xff0c;Chrome浏览器为我们提供了许多扩展的选择&#xff0c;可以让我们高效和省时地完成工作。以下为作者观点&#xff1a; 1. Testsigma Recorder Testsigma Recorder用于记录与网络应用…

Spring 当中的Bean 作用域

Spring 当中的Bean 作用域 文章目录 Spring 当中的Bean 作用域每博一文案1. Spring6 当中的 Bean的作用域1.2 singleton 默认1.3 prototype1.4 Spring 中的 bean 标签当中scope 属性其他的值说明1.5 自定义作用域&#xff0c;一个线程一个 Bean 2. 总结:3. 最后&#xff1a; 每…

AI视频教程下载:用 ChatGPT 和 WordPress 创建赚钱网站

您是否有兴趣开设网站&#xff08;博客&#xff09;&#xff0c;但不知道从何入手&#xff1f; 或者您已经开设了网站&#xff08;博客&#xff09;&#xff0c;但难以从中获利&#xff1f; 别找啦&#xff01; 本课程旨在教授您使用 WordPress 创建成功盈利网站&#xff08;博…

如何让你的排单更快?

一般我们都喜欢做打板借用快速通道&#xff01;但是目前快速通道也是共享通道&#xff0c;独立单元格基本不开发。 想要排单更快&#xff0c;想要隔夜打板&#xff0c;我们到底应该怎么做呢&#xff1f; 想要排单更快&#xff0c;说白了就是要提高你的交易速度&#xff01;一&a…

设计模式Java实现-建造者模式

楔子 小七在2019年的时候&#xff0c;就想写一个关于设计模式的专栏&#xff0c;但是最终却半途而废了。粗略一想&#xff0c;如果做完一件事要100分钟&#xff0c;小七用3分钟热情做的事&#xff0c;最少也能完成10件事情了。所以这一次&#xff0c;一定要把他做完&#xff0…

有人问,Windows 内核和 Linux 内核谁更复杂?

在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「 Linux的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; 作为一个读过两者源码并写过…

基于Springboot的果蔬作物疾病防治系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的果蔬作物疾病防治系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系…

基于JSP的酒店客房管理系统(三)

目录 第四章 系统各模块的实现 4.1客房管理系统首页的实现 4.1.1 客房管理系统首页概述 4.2客房管理系统前台的实现 4.2.1 客房管理系统前台概述 4.2.2 客房管理系统前台实现过程 4.2.3 预定客房信息及客房信息的查询 4.3客房管理系统后台的实现 4.3.1 客房管理系统后…

认识ansible 了解常用模块

ansible是什么&#xff1f; Ansible是一个基于Python开发的配置管理和应用部署工具&#xff0c;现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点&#xff0c;Pubbet和Saltstack能实现的功能&#xff0c;Ansible基本上都可以实现。是自动化运维工具&#xff0…

【Scala---01】Scala简介与环境部署『 Scala简介 | 函数式编程简介 | Scala VS Java | 安装与部署』

文章目录 1. Scala简介2. 函数式编程简介3. Scala VS Java4. 安装与部署 1. Scala简介 Scala是由于Spark的流行而兴起的。Scala是高级语言&#xff0c;Scala底层使用的是Java&#xff0c;可以看做是对Java的进一步封装&#xff0c;更加简洁&#xff0c;代码量约是Java的一半。…

【Osek网络管理测试】[TG3_TC6]等待总线睡眠状态_2

&#x1f64b;‍♂️ 【Osek网络管理测试】系列&#x1f481;‍♂️点击跳转 文章目录 1.环境搭建2.测试目的3.测试步骤4.预期结果5.测试结果 1.环境搭建 硬件&#xff1a;VN1630 软件&#xff1a;CANoe 2.测试目的 验证DUT在满足进入等待睡眠状态的条件时是否进入该状态 …

【搜索技能】外链

文章目录 前言一、外链是什么&#xff1f;二、如何进行外链调查&#xff1f;总结 前言 今儿因为在搜索一个很感兴趣的软件&#xff0c;但是软件信息所在的网址非常有限。因此产生了一个念头&#xff1a;我能不能找到所有的包含了或者是引用了这个网站的网站呢? 调查之下&…