大数据量树形数据表格展示, 虚拟表格,el-table, umy-ui, 表格懒加载

news/2024/7/10 0:23:43 标签: vue, js, 前端

1. 出现的问题

要展示树形数据表格,根据当前点击的表格行去请求新的数据并展示, 基于这种情况遇到以下问题
1). 当树形表格数据层级大于五级且数据量较多时, 浏览器崩溃
2). 当数据条数展示超出500以上时页面明显卡顿, 加载越多越卡直到崩溃
3). 2020-09-18 添加: 火狐浏览器, 底部树形展开然后切换表格展示数据时虚拟表格渲染出现空白如下图
表格出现空白

2. 根据问题找出解决方案

开发使用vue + element-ui 框架 基于el-table 尝试解决方案
猜测是表格数据切换但是虚拟表格定位展示出现问题, 因为重新滚动即可完整展示
解决方案: 重新绘制表格

2.1 不使用树形表格数据, 对数据做平铺展示, 手动模拟树形数据的功能及相关数据处理
// 模拟的操作的元素结构
<template slot-scope="scope">
   <div>
	   <i 
		   v-if="scope.row.hasChildren" 
		   :class="getClassName(scope.row)" 
		   class="level-icon" 
		   @click.stop="load(scope.row, scope.$index)"
		   >
	   </i>
	   <span 
	   	:class="`span-level${scope.row.level}`">
		   {{scope.row.dimenssionName}}
	   </span>
   </div>
</template>

// methods 中的方法 
getTableData () {
	// 对获取的数据做处理
	/*
		1. 对数据做标识处理
		添加level 代表当前数据所处层级关系
		添加expend 代表当前树形结构展示收起状态及icon 展示
		添加loading 代表当前树形结构点击后接口请求加载状态 icon的展示
		添加nodeString 字段标识取上一级的 nodeString字段和当前数据的 id 拼接用于标识展开数据的父子层级关系 
	*/
}
getClassName (row) { // 根据参数设置 icon 以及当前层级
	 return {
	    'el-icon-loading': row.loading,
	    'el-icon-arrow-right': !row.expend && !row.loading,
	    'el-icon-arrow-down': row.expend && !row.loading,
	    [`level${row.level}`]: row.level
	  }
},

load(row, $index) { // 获取数据的方法
	/*
	此处根据当前点击的这一行 row 判断这一行是处于展开还是收起状态,
	如果是展开状态则收起并清除当前节点下的所有子节点
	如果是展开状态则请求新数据并添加到当前位置的后续位置
	同时需要修改按钮的状态
	*/ 
	// 修改按钮的loading 状态
	this.$set(this.tableData[$index], 'loading', true)
	// 获取当前的点击行的展开收起状态
	const expend = this.tableData[$index].expend
	if (expend) { // 处于展开需要收起
		// 因为都是单层数据, 没有循环引用使用 JSON.parse, JSON.stringify 克隆数据
		const data = JSON.parse(JSON.stringify(this.tableData))
		const tableData = data.filter(item => { // 对当前数据进行过滤
			// 通过 nodeString 字段判断 去除的数据一定是当前点击行的子数据
			if (item.nodeString.includes(row.nodeString) && item.level > row.level) {
	            item.expend = false
	            return false
          	} else {
	            return true
          	}
		})
		this.tableData = tableData // 数据重新赋值
		// 修改按钮状态
		this.$set(this.tableData[$index], 'expend', !expend)
		this.$set(this.tableData[$index], 'loading', false)
		return  // 不继续向下执行
	}
	
	// 处于收起状态则进行展开
	try {
		// 请求数据 假设获取的数据为 data 是个数组
		if (!data.length) { // 如果数组没有长度 则去除当前行树形展开按钮
            this.$set(this.tableData[$index], 'hasChildren', false)
        }
		// 对当前点击位置数据进行截取
		const preData = this.tableData.slice(0, $index + 1) // 从开始到点击位置的数据
        const nextData = this.tableData.slice($index + 1) // 从点击位置后一个到结束位置的数据
        data.map(item => { // 添加关键字段意义同getTableData 方法中说明
           item.parentNodeId = row.id
           item.level = row.level + 1
           item.loading = false
           item.nodeString = `${row.nodeString}_${item.id}`
       	})
       	// 拼接数据
       	const tableData = preData.concat(data).concat(nextData)
       	const filterData = tableData.filter(item => {
              let flag = true
              const rowRoot = row.nodeString.split('_')[0]
              if (!item.nodeString.includes(rowRoot) && row.level === 5) { // 剔除根为5级展开的数据, 只保留当前
                if (item.level === 6) {
                  item.expend = false
                  flag = false
                } else if (item.level === 5) {
                  item.expend = false
                }
              }
              return flag
            })
       	// 重新赋值
       	this.tableData = filterData
	} catch (e) { // 关闭icon loading状态
		this.$set(this.tableData[$index], 'loading', false)
	}
}
2.2 以上的数据处理及问题说明

出现的问题:

  1. 多个五级数据展开时, 其他自动收起, 滚动条定位错误,表格出现跳动,展示不准确
  2. 多数据树形展开是表格卡顿

解决办法:

  1. 通过多方查找验证决定使用 umy-ui 大数据量虚拟表格实现

虚拟表格是只渲染少量表格元素, 随着鼠标滚动, 动态的切换数据进行表格数据渲染, 这就解决了多数据量表格卡顿问题

3. 使用umy-ui: u-table 组件

<template>
  <div class="table-box" ref="tableBox">
    <u-table
      :data="tableData"
      style="width: 100%;"
      ref="uTable"
      :max-height="height"
      :data-changes-scroll-top="false"
      :empty-text="emptyText"
      use-virtual
      border
    >
      <!--u-table大数据表格 你需要在列上指定某个列显示展开收起 treeNode属性, 这里我是用自己模拟的所以没有指定treeNode属性-->
          <u-table-column
             :tree-node="true"
             prop="address"
             label="我是树节点"
             fixed
             :width="200"/>
          <u-table-column
             v-for="item in columns"
             :key="item.id"
             :prop="item.prop"
             :label="item.label"
             :width="item.width"/>
    </u-table>
  </div>
// 使用u-table 后对上面数据做了重新处理
load (row, $index) {
	/*
		此处根据当前点击的这一行 row 判断这一行是处于展开还是收起状态,
		如果是展开状态则收起并清除当前节点下的所有子节点
		如果是展开状态则请求新数据并添加到当前位置的后续位置
		同时需要修改按钮的状态
	*/ 
      this.$set(this.tableData[$index], 'loading', true) // 开启loading状态
      const expend = this.tableData[$index].expend // 获取展开状态
      if (expend) {
        const data = JSON.parse(JSON.stringify(this.tableData))
        const tableData = []
        data.map(item => {
          if (item.nodeString.includes(row.nodeString) && item.level > row.level) {
            item.expend = false
          } else {
            tableData.push(item)
          }
        })
        this.tableData = tableData
        this.$set(this.tableData[$index], 'expend', !expend)
        this.$set(this.tableData[$index], 'loading', false)
        return
      }
      try {
        this.axios({ // 请求数据
          url: '/api/tool/info',
          method: 'POST',
          data: params
        }).then(res => {
          if (成功了) {
            const data = JSON.parse(JSON.stringify(res.data.data))
            if (!data.length) { // 异常处理
              this.$set(this.tableData[$index], 'hasChildren', false) // 去除按钮可展开状态
            }
            this.$set(this.tableData[$index], 'expend', !expend)
            this.$set(this.tableData[$index], 'loading', false)
            const preData = this.tableData.slice(0, $index + 1) // 获取点击位置及之前前数据
            const nextData = this.tableData.slice($index + 1) // 点击位置后数据
            const length = preData.length + data.length - 1
            data.map(item => { // 对新获取数据添加标识及层级关系
              item.parentNodeId = row.id
              item.level = row.level + 1
              item.loading = false
              item.length = length
              item.nodeString = `${row.nodeString}_${item.id}`
            })
            const tableData = preData.concat(data).concat(nextData)
  			 因使用虚拟表格没有性能问题, 所以去除收起功能
            // const filterData = tableData.filter(item => { 
            //   let flag = true
            //   const rowRoot = row.nodeString.split('_')[0]
            //   if (!item.nodeString.includes(rowRoot) && row.level === 5) { // 剔除根为5级展开的数据, 只保留当前
            //     if (item.level === 6) {
            //       item.expend = false
            //       flag = false
            //     } else if (item.level === 5) {
            //       item.expend = false
            //     }
            //   }
            //   return flag
            // })
            this.tableData = tableData
          } else {
            this.$set(this.tableData[$index], 'loading', false)
          }
        }, err => {
          console.log(err)
          this.$set(this.tableData[$index], 'loading', false)
        })
      } catch (e) {
        this.$set(this.tableData[$index], 'loading', false)
      }
    }

4. 总结

经过以上处理解决了表格性能问题
umy-ui地址


http://www.niftyadmin.cn/n/1483381.html

相关文章

网络执法官简介

“网络执法官”是一款局域网管理辅助软件&#xff0c;采用网络底层协议&#xff0c;能穿透各客户端防火墙对网络中的每一台主机&#xff08;本文中主机指各种计算机、交换机等配有IP的网络设备&#xff09;进行监控&#xff1b;采用网卡号&#xff08;MAC&#xff09;识别用户&…

C++——数据结构 简单计算器

简单计算器 输入一个只包含 - * / 运算符且运算数都为非负整数的表达式&#xff0c;请计算该表达式的值。 输入格式: 测试数据有多组。对于每组测试&#xff0c;输入一个字符串&#xff08;长度不超过200&#xff09;表示的表达式&#xff0c;整数和运算符之间用一个空格分隔。…

腾讯alloylever使用问题总结, vconsole 生产环境条件展示

1. 安装及使用腾讯 alloylever 安装: npm install alloylever -S引入: import Alloylever from alloylever配置: Alloylever.config({cdn: , // vconsole 网络地址entry: , // 触发显示vconsole 事件绑定元素 可通过Alloylever.entry 函数设置多个元素触发... // 等})2. 遇到的…

响应式开发一招致胜

qq转载于:https://www.cnblogs.com/cuishien/p/10413628.html

ios使用html5切图需要注意的事项

2019独角兽企业重金招聘Python工程师标准>>> 由于公司最近要求开发一个项目是与html5交互的,android端的十分容易,直接将html5等多个包放进去,编写代码即可运行,但是ios的却不行,有一个地方特别需要注意,我就是吃了这个亏,后来查阅了很多资料,最终发现了问题所在: …

vue项目代码优化, 首屏, 白屏, 加载时间等

1. vue项目白屏, 首屏加载内容优化 常用的vue项目首屏内容优化: 路由按需加载, 组件按需加载, 添加loading, 骨架屏等 但是一般没有特殊需求都是只使用按需加载即可2. 遇到的问题 1. 按需加载是好的, 但是如果拆分太细, 会造成js , css文件太多,影响页面资源加载, 和页面的性…

C++数据结构——杨辉三角

杨辉三角 杨辉&#xff0c;字谦光&#xff0c;汉族&#xff0c;钱塘&#xff08;今浙江省杭州&#xff09;人&#xff0c;南宋杰出的数学家。 他曾担任过南宋地方行政官员&#xff0c;为政清廉&#xff0c;足迹遍及苏杭一带。他在总结民间乘除捷算法、“垛积术”、纵横图&#…

1.4 GPU分析

shader 加宏 编译说明glsl转载于:https://www.cnblogs.com/GISCesium/p/10420498.html