浅记一下ElementPlus中的虚拟化表格(el-table-v2)的简单使用

我的需求

同时在一个表格中显示6个甚至更多的传感器数据,数据量在每个传感器每10秒1条数据,一般请求1天的数据。

以6个传感器计算一下数据量:

6 * 24 * 60 * 6 = 51840

一次只能请求到1个传感器的数据,也就是8640条,当查询时间范围变化时,循环请求接口获取数据,并且需要很快的渲染完毕。

效果像这样

我的经历

先使用的 Table(el-table)

调用一次接口反应时间(浏览器网络窗口查看)约在1-2s左右,一次接口的数据使用Table渲染一次时间约是4s左右。

最开始的想法

新添加一个传感器的数据,每一次需要重新渲染一次没有问题。

当切换查询时间后,循环调用时,采用的是------给tableData中直接添加。这会导致在循环调取数据时,每调取一次就会重新渲染一次。出现渲染卡顿问题,6个接口调用完毕且渲染完成,需要20-30s的时间,数据量大的时间会更长,有兴趣的朋友可以试一下。

js 复制代码
<el-table v-loading="loading" element-loading-text="数据加载中":data="tableData"
  height="100%">
  <el-table-column :min-width="leftWidth" :fixed="index == 0" v-for="(column, index) in columns"
    :key="column.prop" :label="column.label" :prop="column.prop"></el-table-column>
</el-table>
······
tableData.value = tableData.value.map((item: any, index: number) => {
    return {
      ...item,
      ['data' + String(sensor.id)]: Number(res.data.Data[index].data).toFixed(3)
    }
})

对最开始的想法优化

在循环调用时,调用一次渲染一次非常慢,第一次优化是拿到所有的数据之后,再将数据添加至tableData,之后同意进行渲染,这种方式快了一点,但没有太大改善。

js 复制代码
const buildTableFromAllData = (allFetched: Array<any>) => {
  if (allFetched.length === 0) return;

  // 第一步:构建 columns
  const newColumns = [
    { prop: 'time', label: '时间' }
  ];
  allFetched.forEach(({ device, gateway }) => {
    newColumns.push({
      prop: 'data' + String(sensor.id),
      label: sensor.name
    });
  });

  // 第二步:对齐时间轴(假设所有设备返回的时间点一致)
  const firstData = allFetched[0].rawData;
  const timeList = firstData.map((item: any) => dayjs(item.time).format('YYYY-MM-DD HH:mm:ss'));

  // 第三步:构建 tableData 行数据
  const newTableData = timeList.map((time: string, index: number) => {
    const row: Record<string, any> = { time };
    allFetched.forEach((_, colIndex) => {
      const value = allFetched[colIndex].rawData[index]?.data;
      const formatted = value ? Number(value).toFixed(3) : '';
      row['data' + String(_.sensor.id)] = formatted;
    });
    return row;
  });

  // 第四步:构建 lineData(用于图表)
  const newLineData = allFetched.map(fetched =>
    fetched.rawData.map((item: any) => Number(item.data).toFixed(3))
  );

  // ✅ 一次性赋值!只触发一次响应式更新
  columns.value = newColumns;
  tableData.value = newTableData;
};

虚拟化表格的接触

在AI的建议下使用虚拟化表格。

ElementPlus中的说明通过虚拟化表格组件,超大数据渲染将不再是一个头疼的问题

使用虚拟化表格之后,渲染速度至少提升一半时间以上。

js 复制代码
<el-auto-resizer>
  <template #default="{ height, width }">
    <el-table-v2 v-loading="loading" element-loading-text="数据加载中" :columns="columns" :data="tableData"
      :width="width" :height="height" fixed />
  </template>
</el-auto-resizer>
······
const buildTableFromAllData = (allFetched: Array<any>) => {
  if (allFetched.length === 0) return;

  const newColumns: any[] = [
    {
      key: 'time',
      dataKey: 'time',
      title: '时间',
      width: 200 * Number(ratio.value),
      fixed: 'left'
    }
  ];

  allFetched.forEach(({ sensor }) => {
    newColumns.push({
      key: 'data' + String(sensor.id),
      dataKey: 'data' + String(device.Deviceid),
      title: sensor.name,
      width: 200 * Number(ratio.value)
    })
  });

  const firstData = allFetched[0].rawData;
  const timeList = firstData.map((item: any) => dayjs(item.time).format('YYYY-MM-DD HH:mm:ss'));

  const newTableData = timeList.map((time: string, index: number) => {
    const row: Record<string, any> = { time };
    allFetched.forEach((_, colIndex) => {
      const value = allFetched[colIndex].rawData[index]?.data;
      const formatted = value ? Number(value).toFixed(3) : '';
      row['data' + String(_.sensor.id)] = formatted;
    });
    return row;
  });
  
  const newLineData = allFetched.map(fetched =>
    fetched.rawData.map((item: any) => Number(item.data).toFixed(3))
  );

  // ✅ 一次性赋值!只触发一次响应式更新
  columns.value = newColumns;
  tableData.value = newTableData;
};

其它问题

问题

其实以上用法已经完全解决了我的问题,但是在电脑浏览器中使用无误,但是一换到手机浏览器或者平板浏览器中,虚拟表格直接滑不动,能看到滚动条,但是就是滑不动,以下是我的解决尝试过程。

AI给的解决方案------添加CSS

查询到滚动的内容是这样的<div class="el-vl__wrapper el-table-v2__body",于是我添加了下面的样式

css 复制代码
:deep(.el-table-v2__main .el-table-v2__body) {
  -webkit-overflow-scrolling: touch !important;
  overflow-y: auto !important;
  overflow-x: auto !important;
  touch-action: pan-x pan-y !important;
}

结果就是没有结果,并没有解决我的问题。

最终解决方案------还是添加CSS,但略有不同

在审查元素的时候发现了一个东西,第二行div中的overflow: hidden;

html 复制代码
<div class="el-vl__wrapper el-table-v2__body" role="rowgroup">
    <div class="" style="position: relative; overflow: hidden; will-change: transform; direction: ltr; height: 1313.11px; width: 2143.33px;"><div style="height: 3000px; width: 2137.33px;">
    ······
    </div>
</div>

怎么给body设置滚动都没有用,因为里面给hidden了,于是添加的CSS变成了这样

css 复制代码
:deep(.el-table-v2__main .el-table-v2__body) {
  -webkit-overflow-scrolling: touch !important;
  overflow-y: auto !important;
  overflow-x: auto !important;
  touch-action: pan-x pan-y !important;
}

OK!成功解决问题,以上就是虚拟化表格的浅用过程,得下次有机会再深入使用!

相关推荐
GISer_Jing4 分钟前
AI赋能前端:从核心概念到工程实践的全景学习指南
前端·javascript·aigc
|晴 天|5 分钟前
前端事件循环:宏任务与微任务的深度解析
前端
不爱吃糖的程序媛13 分钟前
Flutter-OH OAuth 鸿蒙平台适配详细技术文档
javascript·flutter·harmonyos
用户44455436542614 分钟前
Android开发中的封装思路指导
前端
前端OnTheRun20 分钟前
如何禁用项目中的ESLint配置?
javascript·vue.js·eslint
Felixwb66626 分钟前
Python 爬虫框架设计:类封装与工程化实践
前端
前端无涯27 分钟前
APP 内嵌 H5 复制功能实现:从现代 API 到兼容兜底方案
javascript
广州华水科技27 分钟前
潜力榜单2025年单北斗GNSS位移监测高口碑产品推荐
前端
xinyu_Jina29 分钟前
OpenNana 提示词图库:多模态数据检索、分面搜索与前端性能工程
前端
暴富的Tdy33 分钟前
【脚手架创建 Vue3 公共组件库】
前端·npm·npm发布