Element的穿梭框數(shù)據(jù)量大時(shí)點(diǎn)擊全選卡頓的解決方案
現(xiàn)象:我們渲染了9999條數(shù)據(jù),由于transfer組件會(huì)一次性渲染所有數(shù)據(jù),所以一次性渲染這么多,卡個(gè)幾十秒很正常好吧。所以懶加載或者分頁(yè)是基本操作,方案二是分頁(yè)操作。
懶加載的方式可以用EUI的無(wú)限滾動(dòng):https://element.eleme.cn/
即便我們做了懶加載之后,點(diǎn)擊全選依舊是卡頓6秒以上,所以方案一解決的是:即便做了懶加載或者分頁(yè)操作后,用戶(hù)點(diǎn)擊分頁(yè),依舊會(huì)卡頓幾秒的情況。
這個(gè)是因?yàn)閠ransfer的源碼中‘全選判斷'代碼性能差的原因,方案一就是修改transfer的源碼。
我提交了一個(gè)pr,地址是: hhttps://github.com/ElemeFE/element/pull/20282

方案一:復(fù)制EUI的transfer組件,然后進(jìn)行修改,再引入項(xiàng)目目錄
EUI的transfer組件目錄路徑:node_modules\element-ui\packages\transfer,復(fù)制文件夾,然后放入vue項(xiàng)目路徑的

在調(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>
開(kāi)始修改transfer代碼:
打開(kāi)src/common\transfer\src\transfer-panel.vue的組件,
找到updateAllChecked函數(shù),updateAllChecked函數(shù)作用是:我們點(diǎn)擊一個(gè)item就需要判斷,看代碼注釋。
updateAllChecked() {
/*
源碼
this.checkableData是對(duì)象數(shù)組 我們需要的是每個(gè)對(duì)象中的key
所以checkableDataKeys保存著對(duì)象的key的數(shù)組 含義是'可通過(guò)點(diǎn)擊進(jìn)行選擇的item項(xiàng)'的集合
*/
let start = new Date().getTime();
const checkableDataKeys = this.checkableData.map(
item => item[this.keyProp]
);
this.allChecked =
checkableDataKeys.length > 0 &&
/*
從2.4.0到現(xiàn)在都沒(méi)改變 誒,不得不說(shuō)開(kāi)發(fā)團(tuán)隊(duì)是真的忙啊
this.checked保存著'用戶(hù)通過(guò)點(diǎn)擊item選中的item數(shù)組'
如果this.checked存在著checkableDataKeys的每一項(xiàng)的話(huà),那么allChecked就是true,但凡有一項(xiàng)不存在就為false。allChecked代表是否全部選中了。
這里的時(shí)間復(fù)雜度是n^2,狠垃圾
*/
checkableDataKeys.every(item => this.checked.indexOf(item) > -1);
console.log("updateAllCheckedEnd", new Date().getTime() - start);
},
來(lái)看源碼的耗時(shí):

然后我們開(kāi)始重寫(xiě)updateAllChecked函數(shù):
updateAllChecked() {
/*
修改
這里就是高效數(shù)組中含有另一個(gè)數(shù)組的元素的算法
構(gòu)建元素對(duì)象
*/
let start = new Date().getTime();
let checkableDataKeys = this.checkableData.map((item) => {
let keyProps = {};
keyProps[item[this.keyProp]] = true;
return keyProps;
});
// 通過(guò)對(duì)象的k-v對(duì)應(yīng),n(1)的方式尋找數(shù)組中是否存在某元素
this.allChecked =
checkableDataKeys.length > 0 &&
this.checked.length > 0 &&
this.checked.every((item) => checkableDataKeys[item]);
// 上面被注釋的源碼是最耗時(shí)的,所有一直看耗時(shí)就可以了
console.log("updateAllCheckedEnd", new Date().getTime() - start);
},
這樣性能就高好多了,其實(shí)就是基本的前端算法題,目測(cè)EUI的開(kāi)發(fā)者是因?yàn)閼胁挪粚?xiě)的。
來(lái)看修改代碼后的耗時(shí):

明顯快多了。
接下來(lái)是文件:\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),耗時(shí)長(zhǎng)
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);
},
移動(dòng)選中的耗時(shí):

修改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);
},
移動(dòng)選中耗時(shí):

耗時(shí)明顯減少了,這方案的前提就是懶加載或者分頁(yè),我試了一下10w的數(shù)據(jù)量,依舊是不錯(cuò)的。
方案二:分頁(yè)操作
分析
checkBox-group有個(gè)check數(shù)組(用來(lái)記錄已經(jīng)選中的item數(shù)組)和renderItem數(shù)組(實(shí)際渲染的item,由于是分頁(yè),所有不會(huì)渲染所有),如果`check數(shù)組`中有`renderItem數(shù)組`的一項(xiàng),那么該項(xiàng)就會(huì)被標(biāo)記為已選,否則是未選。實(shí)現(xiàn)原理就是單純的check數(shù)組和renderItem數(shù)組進(jìn)行比較。
當(dāng)用戶(hù)點(diǎn)擊全選的時(shí)候,check數(shù)組變成上萬(wàn)條數(shù)據(jù)的數(shù)組,此時(shí)我們渲染了100條數(shù)據(jù),那么就要進(jìn)行10000x100級(jí)別的循環(huán),這就是耗時(shí)的原因所在。
其實(shí),頁(yè)面只渲染了100條數(shù)據(jù),我們沒(méi)必要將上萬(wàn)條數(shù)據(jù)一次性放入check數(shù)組中,我們只需要把這100條數(shù)組放入check數(shù)組,顯示這100條數(shù)據(jù)為已選即可。當(dāng)頁(yè)面渲染了更多數(shù)據(jù)的同時(shí),將新增的數(shù)據(jù)添加進(jìn)check數(shù)組即可。這樣性能大大提升。
方案
我采用的方案如下:
1.只顯示100條數(shù)據(jù)。
2.下拉顯示下100條數(shù)據(jù),上拉顯示上100條數(shù)據(jù)。
3.當(dāng)下拉或者上拉增加渲染數(shù)據(jù)的同時(shí),把新增數(shù)據(jù)添加進(jìn)check數(shù)組。
這些只是大致思路,我已經(jīng)實(shí)現(xiàn)了。還有很多細(xì)節(jié)要處理,想要完善,還得利用對(duì)象的鍵值對(duì)實(shí)現(xiàn)刪除等。
到此這篇關(guān)于Element的穿梭框數(shù)據(jù)量大時(shí)點(diǎn)擊全選卡頓的解決方案的文章就介紹到這了,更多相關(guān)Element 穿梭框卡頓內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue滾動(dòng)軸插件better-scroll使用詳解
這篇文章主要為大家詳細(xì)介紹了vue滾動(dòng)軸插件better-scroll的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
Vue導(dǎo)入Echarts實(shí)現(xiàn)折線(xiàn)散點(diǎn)圖
這篇文章主要為大家詳細(xì)介紹了Vue導(dǎo)入Echarts實(shí)現(xiàn)折線(xiàn)散點(diǎn)圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
Vue自定義指令實(shí)現(xiàn)對(duì)數(shù)字進(jìn)行千分位分隔
對(duì)數(shù)字進(jìn)行千分位分隔后展示應(yīng)該是大部分同學(xué)都做過(guò)的功能了吧,常規(guī)的做法通常是編寫(xiě)一個(gè)工具函數(shù)來(lái)對(duì)數(shù)據(jù)進(jìn)行轉(zhuǎn)換,那么我們可不可以通過(guò)vue指令來(lái)實(shí)現(xiàn)這一功能呢,下面我們就來(lái)探索一下呢2024-02-02
vue實(shí)現(xiàn)頂部左右滑動(dòng)導(dǎo)航
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)頂部左右滑動(dòng)導(dǎo)航,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
vue elementui tree 任意級(jí)別拖拽功能代碼
這篇文章主要介紹了vue elementui tree 任意級(jí)別拖拽功能代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08
Vue 通過(guò)公共字段,拼接兩個(gè)對(duì)象數(shù)組的實(shí)例
今天小編就為大家分享一篇Vue 通過(guò)公共字段,拼接兩個(gè)對(duì)象數(shù)組的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11
vuex存儲(chǔ)復(fù)雜參數(shù)(如對(duì)象數(shù)組等)刷新數(shù)據(jù)丟失的解決方法
今天小編就為大家分享一篇vuex存儲(chǔ)復(fù)雜參數(shù)(如對(duì)象數(shù)組等)刷新數(shù)據(jù)丟失的解決方法。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11
Vue 全家桶實(shí)現(xiàn)移動(dòng)端酷狗音樂(lè)功能
這篇文章主要介紹了Vue 全家桶實(shí)現(xiàn)移動(dòng)端酷狗音樂(lè)功能,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11

