Vue渲染十万级数据卡顿解决方案:pl-table与分批加载实战

作者:雾松时间:2026-10-25 18:54:14浏览:135

本文针对Vue页面渲染十万条数据导致的卡顿问题,对比了Node中间层、虚拟列表及前后端配合三种方案。重点介绍了使用pl-table结合后端分批获取数据(每次500条)的实现方式,通过控制查询状态、UUID校验及最大ID判断,实现流畅的大数据表格渲染,并提供完整代码逻辑。

1. 问题描述

业务场景中,点击查询按钮需一次性加载全部数据,当数据量接近10万条时,前端渲染过程出现严重卡顿甚至页面假死。

2. 常见的解决方案

- 自定义中间层

构建Node.js中间层,由该层负责获取并拆分这10万条数据。

前端直接对接Node.js中间层,而非直接连接后端服务器。

缺点:开发与维护成本较高。

- 虚拟列表

仅渲染可视区域内的DOM节点,非可视区域通过div占位高度隐藏。随浏览器滚动动态创建和销毁DOM元素。

1. 问题描述

虚拟列表实现复杂度极高,建议直接借用成熟的第三方库。

Vue-virtual-scroll-list

React-virtualiszed

- 前后端配合(本问题解决方案)

前端采用pl-table组件加载数据;pl-table是一款专为大数据表格设计的组件,旨在完美解决万级数据渲染卡顿问题。

后端采用循环获取策略,每次仅获取几百条数据,获取后立即进行渲染。

3. 解决方案流程图

采用pl-table结合后端每次读取500条数据后渲染的策略。渲染完成后,若仍有未处理数据,则继续获取后续500条并渲染,直至所有数据读取完毕。

流程图如下图所示:

1. 问题描述

1)点击查询按钮

2)判断是否正在查询(isSearching)

3)若isSearching = true,表示正在查询,此时判断是否需要停止;若需停止则结束查询;若不需停止则继续执行查询过程(无需额外操作)。

4)若isSearching = false,表示未正在查询,此时需设置 isSearching = true;初始化 startId = 0(查询起始ID)。

生成 searchingTaskTag = genUuid()(随机数,用于前后端传递,确保请求与响应的对应关系一致)。

5)调用中间函数fn1,判断当前请求数据的最大ID(maxId)是否小于等于0;若小于等于0,则请求获取最大maxId,并设置 endId = startId + step(查询结束ID)。

6)判断 startId <= maxId 是否为true;若为true,则调用函数fn2,并在请求和响应中携带随机数searchingTaskTag。

7)通过 response.searchingTaskTag === searchingTaskTag 判断是否为同一请求;若是,则将数据累加至列表,同时更新 startId = startId + step,并再次调用步骤5)。

8)判断 startId <= maxId 为false时,表示数据已获取完毕,结束查询。

4. 代码

查询方法

//查询
    handleSearch() {
      //this.isShow = false;
      if (this.isSearching) {
        // 提示用户是否停止查询?
        this.$confirm("确认停止查询?", "提示", {
          type: "warning",
        }).then(() => {
          this.listLoading = false;
          this.searchingTaskTag = "";
          this.isSearching = false;
          this.hardReset = false;
          this.$nextTick(() => {
            this.hardReset = true;
          });
        });
      } else {
        this.isSearching = true;
        this.searchingTaskTag = genUuid();
        this.tableData = [];
        this.startId = 0;
        this.fn1();
      }
    },

中间函数fn1

    async fn1() {
      let startId = this.startId;
      let endId = this.startId + this.step;
      let param = {
        pageNo: this.page,
        pageSize: this.pageSize,
        startId: startId,
        endId: endId,
        searchingTaskTag: this.searchingTaskTag,
      };
      try {
        if (this.maxId <= 0) {
          let response = await getMaxId();
          this.maxId = response.body;
        }
        if (startId <= this.maxId) {
          this.fn2(param);
        } else {
          this.$message.success("查询结束!");
          this.isSearching = false;
        }
      } catch (e) {}
    },
getMaxId() {
      getMaxId()
        .then((resp) => {
          this.maxId = resp.body;
        })
        .catch((error) => {
          this.$message.error(error.body);
        });
    },

fn2 函数

   //获取数据列表
 fn2(param) {
      fn2(param).then(
      (resp) => {
          let tempList = resp.body.content;
          let echoSearchingTaskTag = resp.body.searchingTaskTag;
          if (
            tempList.length > 0 &&
            this.searchingTaskTag == echoSearchingTaskTag
          ) {
            this.tableData.push(...tempList);
           }
          if (this.searchingTaskTag == echoSearchingTaskTag) {
            this.listLoading = false;
            this.startId += this.step;
            this.fn1();
          }
        })
        .catch((error) => {
          this.listLoading = false;
          this.$message.error("获取失败!");
          this.isSearching = false;
          this.flag = false;
        });
      this.listLoading = false;
    },

到此这篇关于vue渲染大量数据时卡顿卡死解决方法的文章就介绍到这了,更多相关vue渲染数据内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

作者最新文章
相关文章
更多