el-table树形数据量过大,导致页面卡顿问题及解决
作者:青云ovo
这篇文章主要介绍了el-table树形数据量过大,导致页面卡顿问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
el-table树形数据量过大,导致页面卡顿问题
需求
el-table
的 树状表格- 当层级和数据过多的时候会出现点击展开和折叠的时候卡顿
- 数据量大,页面异常卡顿
解决
- 采取 懒加载 的方式,将数据 一层层加上去。
- 可以在点击展开的时候像后端请求,也可以从备份的全量数据里面找到对应层级。
- 这种处理方式会在展开过多时慢慢变得卡顿。
注意在模板里添加
lazy :load=“load” :tree-props=“{children: ‘children', hasChildren: ‘hasChildren'}”
// 模板 <el-table row-key="planId" ref="table" :data="tableData" lazy :load="load" :tree-props="{children: 'children', hasChildren: 'hasChildren'}" @selection-change="selectionChange" > <el-table-column type="selection" align="center" /> <el-table-column label="检查明细" prop="inspectDetails" /> </table>
// 数据 data: () => ({ tableData: [], list: [], ids: []}), //方法 mounted() { this.search() } // 获取数据 async search() { // 这儿是将懒加载数据清除,防止调用方法出现页面不更新的情况 this.$set(this.$refs.table.store.states, "lazyTreeNodeMap", {}); this.$set(this.$refs.table.store.states, "treeData", {}); const { rows } = await API_APPRAISE.APR_EXE_OS_R({ projectId: this.$route.query.id, }); // 我这块是将数据需要分组,进行了分组 ,不需要的可以跳过这儿,比如从后端获取到的直接是树形数据 就可以是 // this.list = rows // this.tableData = JSON.parse(JSON.stringify(this.list)).map(item => ({ // ..item, // hasChildren: item.children && item.children.length > 0, // children: null, // idList: [item.planId], // })) let group = this.groupBy(rows, 'testOrgan'); // 备份数据,全部数据 this.list = group.map(item => ({ id: item.id, planId: item.id, children: this.handleTree(item.children) })); // 展示数据 this.tableData = JSON.parse(JSON.stringify(this.list)).map(item => ({ ...item, // 这儿的ids 是每个节点的所有子节点及自己节点的planId, 我后续需要将它传到后端处理,不需要可以删除 ids: this.getTreeNodes(item), // hasChildren 表示需要展示一个箭头图标 hasChildren: item.children && item.children.length > 0, // 只展示一层 children: null, // 记住层级关系 idList: [item.planId], })) }, // 分组函数 groupBy(array, key) { const groupedData = new Map(); for (const item of array) { const group = item[key]; if (!groupedData.has(group)) { groupedData.set(group, []); } groupedData.get(group).push(item); } return Array.from(groupedData, ([id, children]) => ({ id, children })); }, // 懒加载方法, 在点击下拉时会调用 load (tree, treeNode, resolve) { // 层级关系备份 const idCopy = JSON.parse(JSON.stringify(tree.idList)) // 查找下一层数据 let resolveArr = this.list for (const planId of tree.idList) { const tarItem = resolveArr.find((item) => item.planId === planId); if (!tarItem) break; resolveArr = tarItem.children || []; } // 处理下一层数据的属性 resolveArr = JSON.parse(JSON.stringify(resolveArr)) resolveArr.forEach(item => { item.ids = this.getTreeNodes(item) item.hasChildren = item.children && item.children.length > 0 item.children = null item.idList = [...idCopy, item.planId] }) // 渲染子节点 resolve(resolveArr) // 如果需要勾选 那么需要将每一个children重新挂载回去,再调用勾选的方法 this.$nextTick(() => { tree.children = resolveArr if (this.selectIds.includes(tree.paperId)) { this.setChildrenSelect(tree.children, true) } }) }, /** * getTreeNodes 递归函数,用于遍历树形结构 * @param {Object} node - 节点对象 * @returns {Array} - 返回包含节点 planId 的数组 */ getTreeNodes(node) { const result = []; // 遍历当前节点,获取 planId if (node.planId) { result.push(node.planId); } // 遍历子节点 if (node.children && node.children.length > 0) { for (const child of node.children) { // 递归调用,获取子节点的 planId const childIds = this.getTreeNodes(child); result.push(...childIds); } } return result; }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。