需求: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;
}