element 穿梭框性能優(yōu)化的實現(xiàn)
背景
穿梭框處理大數(shù)據(jù)量時,由于渲染的 DOM 節(jié)點過多,造成頁面卡頓的問題。
在盡量不改變組件原有邏輯的前提下,進行優(yōu)化。
解決思路
懶加載 - InfiniteScroll 組件
先從 packages/transfer 中將原組件拷出(或者改源碼重新打包維護私有庫使用)
將
v-infinite-scroll="pageDown" :infinite-scroll-immediate="false"
添加到
<el-checkbox-group
v-show="!hasNoMatch && data.length > 0"
v-model="checked"
:size="size"
:class="{ 'is-filterable': filterable }"
class="el-transfer-panel__list"
v-infinite-scroll="pageDown"
:infinite-scroll-immediate="false"
>
<el-checkbox
class="el-transfer-panel__item"
:label="item[keyProp]"
:disabled="item[disabledProp]"
:key="item[keyProp]"
v-for="item in filteredData">
<option-content :option="item"></option-content>
</el-checkbox>
</el-checkbox-group>
在data中定義pageSize: 20 用來表示每頁數(shù)據(jù)個數(shù)showData: [] 僅用來展示使用,替換上述代碼中實際需要操作的數(shù)據(jù) filteredData
v-for="item in showData">
同時在watch中相應(yīng)的處理
data (data) {
const checked = [];
this.showData = data.slice(0, this.pageSize);
const filteredDataKeys = this.filteredData.map(
(item) => item[this.keyProp]
);
this.checked.forEach((item) => {
if (filteredDataKeys.indexOf(item) > -1) {
checked.push(item);
}
});
this.checkChangeByUser = false;
this.checked = checked;
},
filteredData (filteredData) {
this.showData = filteredData.slice(0, this.pageSize);
}
初始化展示數(shù)量隨意這里取 20。
最后添加滾動到底部時調(diào)用的方法
pageDown () {
const l = this.showData.length;
const totalLength = this.filteredData.length
l < totalLength &&
(this.showData = this.filteredData.slice(0, l + this.pageSize > totalLength ?
totalLength : l + this.pageSize));
},
往下滾動的時候 展示的數(shù)據(jù)長度增加 20(數(shù)量隨意), 超出時展示最大長度。
由此基本解決大數(shù)據(jù)量操作卡頓的問題。由于展示和邏輯層分開,組件的所有操作邏輯無須修改,最小程度減少差異。
新問題
手動滾動到列表末端,再進行搜索操作依然存在卡頓問題。
進階
在滾動過程中,實際上頂端的數(shù)據(jù)依舊無法看見,該數(shù)據(jù)不展示,對用戶體驗也沒有影響,
所以只需展示當前頁的 20 條數(shù)據(jù)。
我們?yōu)閑l-checkbox-group添加一個 ref=scrollContainer 以便操作滾動條,
在data中定義當前頁數(shù) curIndex: 1
并對 pageDown 方法進行修改
pageDown () {
const totalLength = this.filteredData.length
if((this.curIndex*this.pageSize) < totalLength){
this.curIndex ++
const targetLength = this.curIndex * this.pageSize
const endPoint = targetLength > totalLength ? totalLength : targetLength
const startPoint = endPoint - this.pageSize > 0 ? endPoint - this.pageSize : 0
this.showData = this.filteredData.slice(startPoint, endPoint);
this.$refs.scrollContainer.$el.scrollTop = "1px" //滾動條到最上端,銜接下一頁,為 0 可能會觸發(fā)邊界問題
}
}
為此我們還需要添加向上翻頁的方法
InfiniteScroll 指令 只提供向下滾動,我們可以拓展該指令亦可自行添加上滑滾動監(jiān)聽
mounted(){
this.$refs.scrollContainer.$el.addEventListener('scroll', this.pageUp)
},
beforeDestroy(){
this.$refs.scrollContainer.$el.removeEventListener('scroll', this.pageUp)
},
注冊pageUp 方法
pageUp(e){
if(e.target.scrollTop ===0 && this.curIndex>1){
this.curIndex --
const endPoint = this.curIndex * this.pageSize
const startPoint = (this.curIndex-1)* this.pageSize
this.showData = this.filteredData.slice(startPoint, endPoint);
const el = this.$refs.scrollContainer.$el
el.scrollTop = el.scrollHeight - el.clientHeight - 1 // 滾動到最底部,銜接上一頁, -1 防止邊界問題。
}
},
當進行數(shù)據(jù)操作的時候,頁面內(nèi)容變化,滾動條也會隨之變化,為防止不能預(yù)知的翻頁,數(shù)據(jù)改變時,重置滾動條和當前頁碼。
initScroll(){
this.curIndex = 1
this.$refs.scrollContainer.$el.scrollTop = 0
},
同時地,在watch中相應(yīng)時候執(zhí)行 initScroll
data(){
...
this.initScroll()
...
},
filteredData (filteredData) {
...
this.initScroll()
}
至此大數(shù)據(jù)量的穿梭框,性能大為改善。
到此這篇關(guān)于element 穿梭框性能優(yōu)化的實現(xiàn)的文章就介紹到這了,更多相關(guān)element 穿梭框性能優(yōu)化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue?模板循環(huán)繪制多行上傳文件功能實現(xiàn)
這篇文章主要為大家介紹了vue?模板循環(huán)繪制多行上傳文件功能實現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-07-07

