您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“怎么解決Element的穿梭框數(shù)據(jù)量大時點擊全選卡頓問題”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!
現(xiàn)象:我們渲染了9999條數(shù)據(jù),由于transfer組件會一次性渲染所有數(shù)據(jù),所以一次性渲染這么多,卡個幾十秒很正常好吧。所以懶加載或者分頁是基本操作,方案二是分頁操作。
懶加載的方式可以用EUI的無限滾動
即便我們做了懶加載之后,點擊全選依舊是卡頓6秒以上,所以方案一解決的是:即便做了懶加載或者分頁操作后,用戶點擊分頁,依舊會卡頓幾秒的情況。
這個是因為transfer的源碼中‘全選判斷'代碼性能差的原因,方案一就是修改transfer的源碼。
我提交了一個pr,地址是: hhttps://github.com/ElemeFE/element/pull/20282
EUI的transfer組件目錄路徑:node_modules\element-ui\packages\transfer,復制文件夾,然后放入vue項目路徑的
在調(diào)用EUI的transfer的地方引入公共的組件transfer,
<template> <Transfer v-model="value" :data="data"></Transfer> </template> <script> import Transfer from '../common/transfer' export default { components:{ Transfer:Transfer }, //省略 </script>
開始修改transfer代碼:
打開src/common\transfer\src\transfer-panel.vue的組件,
找到updateAllChecked函數(shù),updateAllChecked函數(shù)作用是:我們點擊一個item就需要判斷,看代碼注釋。
updateAllChecked() { /* 源碼 this.checkableData是對象數(shù)組 我們需要的是每個對象中的key 所以checkableDataKeys保存著對象的key的數(shù)組 含義是'可通過點擊進行選擇的item項'的集合 */ let start = new Date().getTime(); const checkableDataKeys = this.checkableData.map( item => item[this.keyProp] ); this.allChecked = checkableDataKeys.length > 0 && /* 從2.4.0到現(xiàn)在都沒改變 誒,不得不說開發(fā)團隊是真的忙啊 this.checked保存著'用戶通過點擊item選中的item數(shù)組' 如果this.checked存在著checkableDataKeys的每一項的話,那么allChecked就是true,但凡有一項不存在就為false。allChecked代表是否全部選中了。 這里的時間復雜度是n^2,狠垃圾 */ checkableDataKeys.every(item => this.checked.indexOf(item) > -1); console.log("updateAllCheckedEnd", new Date().getTime() - start); },
來看源碼的耗時:
然后我們開始重寫updateAllChecked函數(shù):
updateAllChecked() { /* 修改 這里就是高效數(shù)組中含有另一個數(shù)組的元素的算法 構(gòu)建元素對象 */ let start = new Date().getTime(); let checkableDataKeys = this.checkableData.map((item) => { let keyProps = {}; keyProps[item[this.keyProp]] = true; return keyProps; }); // 通過對象的k-v對應,n(1)的方式尋找數(shù)組中是否存在某元素 this.allChecked = checkableDataKeys.length > 0 && this.checked.length > 0 && this.checked.every((item) => checkableDataKeys[item]); // 上面被注釋的源碼是最耗時的,所有一直看耗時就可以了 console.log("updateAllCheckedEnd", new Date().getTime() - start); },
這樣性能就高好多了,其實就是基本的前端算法題,目測EUI的開發(fā)者是因為懶才不寫的。
來看修改代碼后的耗時:
明顯快多了。
接下來是文件:\src\common\transfer\src\main.vue,找到addToRight函數(shù)
addToRight() { let currentValue = this.value.slice(); const itemsToBeMoved = []; const key = this.props.key; let start = new Date().getTime(); // 此處套了兩層循環(huán),耗時長 this.data.forEach((item) => { const itemKey = item[key]; if ( this.leftChecked.indexOf(itemKey) > -1 && this.value.indexOf(itemKey) === -1 ) { itemsToBeMoved.push(itemKey); } }); console.log("addToRightEnd", new Date().getTime() - start); currentValue = this.targetOrder === "unshift" ? itemsToBeMoved.concat(currentValue) : currentValue.concat(itemsToBeMoved); this.$emit("input", currentValue); this.$emit("change", currentValue, "right", this.leftChecked); },
移動選中的耗時:
修改addToRight函數(shù),
addToRight() { let start = new Date().getTime(); let currentValue = this.value.slice(); const itemsToBeMoved = []; const key = this.props.key; // 修改 let leftCheckedKeyPropsObj = {}; this.leftChecked.forEach((item, index) => { leftCheckedKeyPropsObj[item] = true; }); let valueKeyPropsObj = {}; this.value.forEach((item, index) => { valueKeyPropsObj[item] = true; }); this.data.forEach((item) => { const itemKey = item[key]; if ( leftCheckedKeyPropsObj[itemKey] && !valueKeyPropsObj[itemKey] ) { itemsToBeMoved.push(itemKey); } }); console.log("addToRightEnd", new Date().getTime() - start); currentValue = this.targetOrder === "unshift" ? itemsToBeMoved.concat(currentValue) : currentValue.concat(itemsToBeMoved); this.$emit("input", currentValue); this.$emit("change", currentValue, "right", this.leftChecked); },
移動選中耗時:
耗時明顯減少了,這方案的前提就是懶加載或者分頁,我試了一下10w的數(shù)據(jù)量,依舊是不錯的。
checkBox-group有個check數(shù)組(用來記錄已經(jīng)選中的item數(shù)組)和renderItem數(shù)組(實際渲染的item,由于是分頁,所有不會渲染所有),如果`check數(shù)組`中有`renderItem數(shù)組`的一項,那么該項就會被標記為已選,否則是未選。實現(xiàn)原理就是單純的check數(shù)組和renderItem數(shù)組進行比較。
當用戶點擊全選的時候,check數(shù)組變成上萬條數(shù)據(jù)的數(shù)組,此時我們渲染了100條數(shù)據(jù),那么就要進行10000x100級別的循環(huán),這就是耗時的原因所在。
其實,頁面只渲染了100條數(shù)據(jù),我們沒必要將上萬條數(shù)據(jù)一次性放入check數(shù)組中,我們只需要把這100條數(shù)組放入check數(shù)組,顯示這100條數(shù)據(jù)為已選即可。當頁面渲染了更多數(shù)據(jù)的同時,將新增的數(shù)據(jù)添加進check數(shù)組即可。這樣性能大大提升。
我采用的方案如下:
1.只顯示100條數(shù)據(jù)。
2.下拉顯示下100條數(shù)據(jù),上拉顯示上100條數(shù)據(jù)。
3.當下拉或者上拉增加渲染數(shù)據(jù)的同時,把新增數(shù)據(jù)添加進check數(shù)組。
這些只是大致思路,我已經(jīng)實現(xiàn)了。還有很多細節(jié)要處理,想要完善,還得利用對象的鍵值對實現(xiàn)刪除等。
“怎么解決Element的穿梭框數(shù)據(jù)量大時點擊全選卡頓問題”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。