el-table樹(shù)形數(shù)據(jù)量過(guò)大,導(dǎo)致頁(yè)面卡頓問(wèn)題及解決
el-table樹(shù)形數(shù)據(jù)量過(guò)大,導(dǎo)致頁(yè)面卡頓問(wèn)題
需求
el-table的 樹(shù)狀表格- 當(dāng)層級(jí)和數(shù)據(jù)過(guò)多的時(shí)候會(huì)出現(xiàn)點(diǎn)擊展開(kāi)和折疊的時(shí)候卡頓
- 數(shù)據(jù)量大,頁(yè)面異??D
解決
- 采取 懶加載 的方式,將數(shù)據(jù) 一層層加上去。
- 可以在點(diǎn)擊展開(kāi)的時(shí)候像后端請(qǐng)求,也可以從備份的全量數(shù)據(jù)里面找到對(duì)應(yīng)層級(jí)。
- 這種處理方式會(huì)在展開(kāi)過(guò)多時(shí)慢慢變得卡頓。
注意在模板里添加
lazy
:load=“l(fā)oad”
: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="檢查明細(xì)" prop="inspectDetails" />
</table>
// 數(shù)據(jù)
data: () => ({ tableData: [], list: [], ids: []}),
//方法
mounted() {
this.search()
}
// 獲取數(shù)據(jù)
async search() {
// 這兒是將懶加載數(shù)據(jù)清除,防止調(diào)用方法出現(xiàn)頁(yè)面不更新的情況
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,
});
// 我這塊是將數(shù)據(jù)需要分組,進(jìn)行了分組 ,不需要的可以跳過(guò)這兒,比如從后端獲取到的直接是樹(shù)形數(shù)據(jù) 就可以是
// 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');
// 備份數(shù)據(jù),全部數(shù)據(jù)
this.list = group.map(item => ({
id: item.id,
planId: item.id,
children: this.handleTree(item.children)
}));
// 展示數(shù)據(jù)
this.tableData = JSON.parse(JSON.stringify(this.list)).map(item => ({
...item,
// 這兒的ids 是每個(gè)節(jié)點(diǎn)的所有子節(jié)點(diǎn)及自己節(jié)點(diǎn)的planId, 我后續(xù)需要將它傳到后端處理,不需要可以刪除
ids: this.getTreeNodes(item),
// hasChildren 表示需要展示一個(gè)箭頭圖標(biāo)
hasChildren: item.children && item.children.length > 0,
// 只展示一層
children: null,
// 記住層級(jí)關(guān)系
idList: [item.planId],
}))
},
// 分組函數(shù)
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
}));
},
// 懶加載方法, 在點(diǎn)擊下拉時(shí)會(huì)調(diào)用
load (tree, treeNode, resolve) {
// 層級(jí)關(guān)系備份
const idCopy = JSON.parse(JSON.stringify(tree.idList))
// 查找下一層數(shù)據(jù)
let resolveArr = this.list
for (const planId of tree.idList) {
const tarItem = resolveArr.find((item) => item.planId === planId);
if (!tarItem) break;
resolveArr = tarItem.children || [];
}
// 處理下一層數(shù)據(jù)的屬性
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]
})
// 渲染子節(jié)點(diǎn)
resolve(resolveArr)
// 如果需要勾選 那么需要將每一個(gè)children重新掛載回去,再調(diào)用勾選的方法
this.$nextTick(() => {
tree.children = resolveArr
if (this.selectIds.includes(tree.paperId)) {
this.setChildrenSelect(tree.children, true)
}
})
},
/**
* getTreeNodes 遞歸函數(shù),用于遍歷樹(shù)形結(jié)構(gòu)
* @param {Object} node - 節(jié)點(diǎn)對(duì)象
* @returns {Array} - 返回包含節(jié)點(diǎn) planId 的數(shù)組
*/
getTreeNodes(node) {
const result = [];
// 遍歷當(dāng)前節(jié)點(diǎn),獲取 planId
if (node.planId) {
result.push(node.planId);
}
// 遍歷子節(jié)點(diǎn)
if (node.children && node.children.length > 0) {
for (const child of node.children) {
// 遞歸調(diào)用,獲取子節(jié)點(diǎn)的 planId
const childIds = this.getTreeNodes(child);
result.push(...childIds);
}
}
return result;
}
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue.js實(shí)現(xiàn)簡(jiǎn)易折疊面板
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)易折疊面板,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
vue中頁(yè)面跳轉(zhuǎn)攔截器的實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于vue中頁(yè)面跳轉(zhuǎn)攔截器的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-08-08
vue?cli2?和?cli3去掉eslint檢查器報(bào)錯(cuò)的解決
這篇文章主要介紹了vue?cli2?和?cli3去掉eslint檢查器報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
vue electron應(yīng)用調(diào)exe程序的實(shí)現(xiàn)步驟
這篇文章主要介紹了vue electron應(yīng)用調(diào)exe程序的實(shí)現(xiàn)步驟,用Python寫了一個(gè)本地服務(wù)編譯成exe程序,在electron程序啟動(dòng)后,自動(dòng)執(zhí)行exe程序,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下2024-02-02
Vue3利用自定義指令進(jìn)行內(nèi)容控制的實(shí)現(xiàn)方法
Vue3作為一個(gè)漸進(jìn)式JavaScript框架,提供了強(qiáng)大的自定義指令功能,使得權(quán)限控制變得既簡(jiǎn)單又高效,本文將詳細(xì)介紹如何在Vue3中使用自定義指令來(lái)判斷內(nèi)容是否顯示,以滿足不同用戶權(quán)限下的界面展示需求,需要的朋友可以參考下2024-04-04
vue實(shí)現(xiàn)列表垂直無(wú)縫滾動(dòng)
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)列表垂直無(wú)縫滾動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
Vue使用路由鉤子攔截器beforeEach和afterEach監(jiān)聽(tīng)路由
這篇文章主要介紹了Vue使用路由鉤子攔截器beforeEach和afterEach監(jiān)聽(tīng)路由,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
淺談Vue為什么不能檢測(cè)數(shù)組變動(dòng)
這篇文章主要介紹了淺談Vue為什么不能檢測(cè)數(shù)組變動(dòng),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10

