浅记一下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!成功解决问题,以上就是虚拟化表格的浅用过程,得下次有机会再深入使用!

相关推荐
一行代码一行诗++7 分钟前
注释是什么和注释该怎么写(C语言)
java·前端·javascript
涂兵兵_青石疏影14 分钟前
beginPath-vs-save详解
前端
陈振wx:zchen200815 分钟前
前端-面试题-JavaScript
javascript·前端面试题
泽_浪里白条26 分钟前
我在 Superset 6.x 做自定义图表 + Embedded SDK 集成的实战复盘(附踩坑清单)
前端·数据可视化
幽络源小助理43 分钟前
小六壬排盘工具源码 自适应双端 纯原生HTML+JS
前端·javascript·html
Championship.23.242 小时前
Open Source Pipeline Skill深度解析:自动化开源贡献全流程
前端·javascript·html
Bigger2 小时前
🧠 前端岗位的"结构性调整":现象背后的冷思考
前端·程序员·ai编程
薯老板2 小时前
vue组件之间的通信
前端·vue.js
迪菲赫尔曼2 小时前
从 0 到 1 打造工业级推理控制台:UltraConsole(Ultralytics + FastAPI + React)开源啦!
前端·yolo·react.js·计算机视觉·开源·fastapi
万邦科技Lafite2 小时前
京东开放API接口:item_get返回参数指南
java·前端·javascript·api·电商开放平台