• 后端一次性返回10万条数据,使用vue,你该如何渲染?


    vue 解决同时加载万条级数据,页面渲染卡顿问题

    1. 问题描述

    由于业务需求,需要在一个页面中点击查询按钮时加载出所有的数据,但数据量有近10万条,渲染出现卡顿,页面卡死。

    2. 常见的解决方案

    - 自定义中间层
    自定义nodejs中间层,获取并拆分这10w条数据,
    前端对接nodejs中间层,而不是服务器
    缺点:成本高
    - 虚拟列表
    只渲染可视区域DOM,其他隐藏区域不显示,只用div撑起高度,随着浏览器滚动,创建和销毁DOM。
    在这里插入图片描述
    虚拟列表实现起来非常复杂,可借用第三方lib
    Vue-virtual-scroll-list
    React-virtualiszed
    - 前后端配合(本问题解决方案)
    前端使用pl-table加载数据;pl-table(大数据表格,完美解决万级数据渲染卡顿问题)
    后端循环获取数据,每次只获取几百条数据,获取后就进行渲染。

    3. 解决方案流程图

    使用pl-table + 每次从后端读取500条数据后就渲染 ,渲染完成后如果还有数据继续获取数据500条并渲染,直至数据读取完成。
    流程图如下图所示:

    请添加图片描述

    1)点击查询按钮
    2)判断是否正在查询(isSearching)
    3)isSearching = true ;正在查询时判断是否需要停止,需要停止则查询结束;不需要停止则继续查询过程(不需要额外操作)。
    4)isSearching = false ;没有正在查询,这时需要设置 isSearching = true;startId = 0 (查询的开始id);
    searchingTaskTag = genUuid()// 随机数(用来在前后端传递,保证是同一个查询)
    5)调用中间fn1函数,判断当前请求数据的最大Id是否小于等于0,如果小于等于0 则请求出最大maxId,并设置endId = startId + step(查询的结束Id);
    6) 判断startId <= maxId 为true,则调用函数fn2,随机数searchingTaskTag请求和响应中携带。
    7)根据response.searchingTaskTag === searchingTaskTag 判断是否是同一个请求,如果是数据则累加进去,同时 startId = startId + step;并去调用步骤5)。
    8)判断startId <= maxId 为false,则结束查询。

    4. 代码

    1. 查询方法
    //查询
        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();
          }
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    1. 中间函数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);
            });
        },
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    1. 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;
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
  • 相关阅读:
    猿创征文|〖Python 数据库开发实战 - Python与MySQL交互篇⑯〗- 项目实战 - 实现用户管理 - 新增用户功能
    从零开发短视频电商 Spring事务嵌套问题
    【创作中心】自定义模板的使用
    信息安全:网络物理隔离技术原理与应用.
    性能优化:TCP连接优化之四次挥手
    JVM篇---第四篇
    110道 MySQL面试题及答案 (持续更新)
    Jmeter 自动化性能测试常见问题汇总
    软考 系统架构设计师系列知识点之基于架构的软件开发方法ABSD(4)
    pytest一些常见的插件
  • 原文地址:https://blog.csdn.net/qq_25529689/article/details/126442416