欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Tree組件實現(xiàn)支持50W數(shù)據(jù)方法剖析

 更新時間:2022年08月11日 08:48:18   作者:誰說不啊  
這篇文章主要為大家介紹了Tree組件實現(xiàn)支持50W數(shù)據(jù)的方法剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

出師未捷身先死

有用戶在 fes-design VIP群 吐槽 Tree 組件在處理一萬條左右數(shù)據(jù)時很卡。但是 fes-design 已重視大數(shù)據(jù)場景,提供基礎的虛擬列表組件,以及選擇器、表格、樹形、級聯(lián)等組件基于虛擬列表處理了大數(shù)據(jù)場景,為啥 Tree 組件還卡呢?

Tree 自身的復雜性

Tree 數(shù)據(jù)結構特性決定 Tree 組件中父子節(jié)點存在關聯(lián),以選中功能為例:

Select:選中只影響自身狀態(tài)。

Tree:當開啟父子關聯(lián)時,選中某個節(jié)點時,其所有子孫節(jié)點全部選中,同時需計算父輩節(jié)點是否為全選中。

虛擬滾動帶來的復雜性

虛擬滾動是指根據(jù)滾動距離計算當前視野范圍需要展示的內容。不管有多少數(shù)據(jù),只渲染視野范圍內的選項,大大減少了 Vue 實例的創(chuàng)建,性能無比優(yōu)越。因為虛擬滾動只接受一維數(shù)組結構,所以Tree 組件在初始化時需要把樹狀結構數(shù)據(jù)按照展示順序拍平為一維數(shù)組。那么展開關閉的功能就變得復雜了!

不考慮虛擬滾動方案時節(jié)點會這么設計:

<div class="node">
    <div>{{ node.label }}</div>
    <div v-show="node.expanded" v-for="child in node.children">
            <Node node="child"/> 
    </div>
</div>

展開關閉只需要改變 node.expanded。

考慮虛擬滾動方案時節(jié)點會這么設計:

<div class="node">
    <div>{{ node.label }}</div>
</div>

計算所有子孫節(jié)點狀態(tài),判斷節(jié)點是否顯示,如果顯示則把當前節(jié)點丟到虛擬滾動的一維數(shù)組中。

查問題

先用chrome的性能測試工具看看問題在哪:

可以找到耗時的代碼語句,下一步干掉他們。

怎么做

緩存數(shù)據(jù)

Tree 組件在初始化時會把樹狀結構數(shù)據(jù)按照展示順序拍平為一維數(shù)組,在這個過程中,記錄每個節(jié)點的父級節(jié)點為indexPath 和所有子孫節(jié)點childrenPath。在后續(xù)邏輯中經常會用到:

// 當選中某個節(jié)點時,只需要處理此節(jié)點相關上下節(jié)點狀態(tài)
if (checkingNode) {
    const { indexPath } = checkingNode;
    indexPath.slice(0).reverse().forEach(computeIndeterminate);
    checkingNode.hasChildren &&
        checkingNode.childrenPath.forEach(
            (key: TreeNodeKey) => {
                const node = nodeList.get(key);
                node.isIndeterminate.value = false;
            },
        );
    checkingNode = null;
}

減少響應式數(shù)據(jù)

在優(yōu)化前所有節(jié)點都會丟到nodeList中:

const nodeList = reactive<TreeNodeList>({});

// 轉換節(jié)點數(shù)據(jù)
const copy = transformNode(node, indexPath, level);
nodeList[copy.value] = copy;

數(shù)據(jù)量上來后,數(shù)據(jù)響應式處理耗時非常大。所以我們不要把整個對象一股腦弄成響應式的,只把需要的字段設置為響應式的。

Tree節(jié)點需要緩存的內部狀態(tài)有是否開展、是否全選、是否選中,所以只需要這三個字段為響應式:

const nodeList: Map<TreeNodeKey, InnerTreeOption> = new Map();

f (!nodeList.get(value)) {
    // Object.assign比解構快很多
    copy = Object.assign({}, newItem);
    copy.isExpanded = ref(false);
    copy.isIndeterminate = ref(false);
    copy.isChecked = ref(false);
}

nodeList.set(copy.value, copy);

用更快的 JS 語法

1、Array.concat 性能比較慢,改為使用賦值

export function concat(arr: any[], arr2: any[]) {
    const arrLength = arr.length;
    const arr2Length = arr2.length;
    arr.length = arrLength + arr2Length;
    for (let i = 0; i < arr2Length; i++) {
    arr[arrLength + i] = arr2[i];
    }
    return arr;
}

2、Map 的查找性能比 Object 稍好

const nodeList = {} ;

改為使用

const nodeList = new Map();

3、解構語法比較慢,改為使用Object.assign

扣細節(jié)

1、computeCurrentData 是執(zhí)行非常耗時的函數(shù),由于 watch 兩個變量,在初始化時會執(zhí)行兩次,加上debounce只需要執(zhí)行一次。

watch(
    [currentExpandedKeys, transformData],
    debounce(() => {
        if (isSearchingRef.value) return;
        computeCurrentData();
    }, 10),
    {
        immediate: true,
    },
);

2、葉子節(jié)點不需要計算isExpanded

 if (node.hasChildren) {
    node.isExpanded.value = expandedKeys.includes(key);
 }

3、計算顯示的節(jié)點時,可以先判斷是否由展開或者關閉節(jié)點觸發(fā)的計算,如果是則只需要計算此節(jié)點子孫和父級節(jié)點狀態(tài),而不需要計算全部節(jié)點

const computeCurrentData = ()=> {
    if(expandingNode) {
        // 計算此節(jié)點相關節(jié)點
        return
    }
    // 遍歷所有節(jié)點
}

類似這種細節(jié)非常多,通過性能測試工具和自己經驗能找到很多地方,積少成多,性能能提升不少。

數(shù)據(jù)結構一致性的魅力

以收起節(jié)點為例:

常規(guī)思路是:當點擊收起節(jié)點時,判斷當前所有子孫節(jié)點是否在顯示數(shù)據(jù)數(shù)組中,如果在就刪掉。復雜度是O(n^2)。

但是可以換個思路:由于childrenPath和currentData的順序一致,只需要遍歷一次childrenPath,判斷是是否為當前節(jié)點下一個節(jié)點,如果是,刪掉就好。復雜度是O(n)

const deleteNode = (keys: TreeNodeKey[], index: number) => {
    let len = 0;
    keys.forEach((key) => {
        if (key === currentData.value[index + len]) {
            len += 1;
        }
    });
    currentData.value.splice(index, len);
};

const index = currentData.value.indexOf(expandingNode.value);
deleteNode(expandingNode.childrenPath, index + 1);

Tree 的代碼中有很多地方,可以通過特殊的數(shù)據(jù)結構來減少或者避免循環(huán),性能提升非常大!

歡迎來體驗: fes-design

以上就是Tree組件實現(xiàn)支持50W數(shù)據(jù)方法剖析的詳細內容,更多關于Tree組件50W數(shù)據(jù)的資料請關注腳本之家其它相關文章!

相關文章

最新評論