原因分析
element-ui のツリー フォームでは、レベルやデータが多すぎると、クリックして展開したり折りたたんだりするとフリーズします。データ量は約30×4×2×3×10=7200となります。
ソースコードのロジックがおかしいのではないかと思い、ソースコードをデバッグしましたが原因がわからず、同僚に相談したところ、dom要素が多すぎることが原因であることが分かりました。
すべてのデータを一度にロードすると、折りたたまれた要素はロードされますが、スタイルは display: none; になります。
クリックして展開すると表示スタイルを変更します。要素の位置が変わったり、ページがリフローしたり、要素数が多いためオーバーヘッドが高くなります。
そこで、遅延読み込み方式を採用し、データをレイヤーごとに追加します。クリックして展開するときにバックエンドにリクエストを送信したり、バックアップされた全データから対応するレベルを見つけたりすることができます。
この処理方法は拡張しすぎると徐々に行き詰ってしまうので、ワンクリックで最初の階層に戻って子ノードを全てアンインストールできるようなロジックを設ける必要があります。
コードを解決する
フォームコードを初期化します。
this.tableDataCopy = res.resultValue || [] // 备份的全量数据
this.tableData = JSON.parse(JSON.stringify(res.resultValue)).map(item => {
// 展示数据
// hasChildren 表示需要展示一个箭头图标
item.hasChildren = item.list && item.list.length > 0
// 只展示一层
// 如果有children数据,会自动加载,就不是懒加载了,也可以配置tree-props里面的children为其他字段
item.list = null
// 记住层级关系
item.idList = [item.objId]
return item
})
遅延読み込みコード:
// 展开
load (tree, treeNode, resolve) {
// 层级关系备份
const idCopy = JSON.parse(JSON.stringify(tree.idList))
// 查找下一层数据
let resolveArr = this.tableDataCopy
let id
// eslint-disable-next-line
while (id = tree.idList.shift()) {
const tarItem = resolveArr.find(item => item.objId === id)
resolveArr = tarItem.list
}
// 处理下一层数据的属性
resolveArr = JSON.parse(JSON.stringify(resolveArr))
resolveArr.forEach(item => {
item.hasChildren = item.list && item.list.length > 0
item.list = null
// 此处需要深拷贝,以防各个item的idList混乱
item.idList = JSON.parse(JSON.stringify(idCopy))
item.idList.push(item.objId)
})
// 渲染子节点
resolve(resolveArr)
},
この記事は、展開、折り畳み、フリーズする大量のデータを含むツリー状のテーブルである element-ui el-tableから転送されています。