背景:需要渲染一个树状结构的表格,但是表格数据量可能非常的大,用户电脑配置又低,数据全部展开后页面非常的卡顿,急需优化。
问题分析:经过排查,加载大数据量时,主要有两个问题,一个是渲染问题,一个是内存问题
解决思路:树状结构改为懒加载
尝试后发现,虽然懒加载能解决刚进入页面时加载量大的问题,但是当用户点开节点再关闭时,已经加载的数据节点还是会以display:none
的形式存在于页面中,这样如果展开多几个节点的话,仍然会造成dom节点数过多,内存升高,页面卡顿的问题。所以就希望能够在节点折叠起来的同时,移除掉这个节点里面的子节点,减少当下开销,当然这也是无奈之举,在节点展开和合并的那一刻,dom新建和销毁的开销也是巨大的,卡一时和卡一世的抉择而已。
下面记录下代码
// 懒加载部分不写了,按照el-table的api 使用lazy和load即可,需要注意的是,el-table中用lazy时,
// 需要先用data设置初始值,这点是与el-tree的lazy不同的。当前版本element-plus2.8.0
// 如何在合并的同时清楚掉节点下的数据呢,这个操作属于魔改,api下没有
/**
* 解决方式是通过查看el-table的源码发现的,在节点展开时,el-table会记录当前节点下的数据,并修改节点加载*状态,所以在收起时,做逆向操作即可
*/
const expandChange = (nodeData, expanded) => {
if(!expanded) {
const key = nodeData.id
// 清除store中该节点的lazyTreeNodeMap数据
tableRef.value.store.states.lazyTreeNodeMap.value[key] = []
// 恢复状态
if (tableRef.value.store.states.treeData.value[key]) {
tableRef.value.store.states.treeData.value[key].expanded = false
delete tableRef.value.store.states.treeData.value[key].loaded
}
}
}
/**
* lazy状态下,配置expand-row-keys无效,如果想展开第一级的话,需要手动调用下
*调用方式为:tableRef.value.store.loadOrToggle(rowData)
*/
这种修改方式的合理性有待商榷,至少解了燃眉之急,如有大佬有更好的方式,还请不吝赐教。