iView
之Select
組件在機能上的優化
我們公司的組件庫是基於iView
比較早的版本修改后的僅供公司內部運用的組件庫,因此在運用的過程當中就會碰到一些題目。接下來本文會對照Select
組件在機能上做出的優化。
Debounce
函數
我們先來回憶一下debounce
函數的運用場景:在前端頁面我們會碰到一些頻仍觸發的事宜;比方
鼠標的挪動
mousemove
事宜;
window
對象的resize
、scroll
事宜;
keydown
,keyup
事宜;
現實的運用過程當中我們可以不須要每次觸發事宜的時刻都去響應當事宜,我們每每須要當用戶住手操縱若干ms
後去響應事宜。這個時刻我們就須要用到debounce
函數了。下面是一段debounce
函數
export function debounce(fn) {
let waiting;
return function() {
if (waiting) return;
waiting = true;
const context = this,
args = arguments;
const later = function() {
waiting = false;
fn.apply(context, args);
};
this.$nextTick(later);
};
}
這段代碼的意義的意義是當DOM更新後去響應這個事宜,而且DOM更新后只會實行一次
有了這些學問的預備我們便可以來談談運用這個組件碰到的機能題目了。
低版本iview
Select組件碰到的題目
在運用低版本的組件過程當中,當數據量很大比方某個select
選擇器內里有500條以至更多的數據時,舉行隱約搜刮有可以卡死頁面,封閉頁面有耽誤。
湧現該題目的緣由
在Select
組件的mounted
鈎子中有三個監聽,分別是組件增加,刪除,和選中時監聽事宜。在監聽事宜中會去遍歷Select
當中的一切子組件做出響應的轉變。
//監聽子組件的移除
this.$on('remove',() => {
if (!this.remote) {
this.modelToQuery();
this.$nextTick(() => this.broadcastQuery(''));
} else {
this.findChild((child) => {
child.updateSearchLabel(); // #1865
child.selected = this.multiple ? this.model.indexOf(child.value) > -1 : this.model === child.value;
});
}
this.slotChange();
this.updateOptions(true);
})
查找這個監聽的關照對象發明恰是Select
的子組件在燒毀或者是建立時關照父組件做出響應的變化。
//組件燒毀時關照父組件
beforeDestroy () {
this.dispatch('iSelect', 'remove');
this.$off('on-select-close', this.onSelectClose);
this.$off('on-query-change',this.onQueryChange);
}
那末題目就出在這裏了,當有大批的子組件時,每個組件移除,父組件須要遍歷一次。如許就拖累機能。
處理辦法
既然前面提到debounce
函數,想必人人應當想到要怎樣處理了。運用debounce
函數可以處理這個題目,我們只須要一切子組件燒毀時關照父組件一次就夠了。引入debounce
函數后經本人測試基本上處理了卡頓以及卡死的題目,代碼以下。
//select組件mounted函數當中去監聽 append 、remove 事宜
this.$on('append', this.debouncedAppendRemove());
this.$on('remove', this.debouncedAppendRemove());
//引入debounce函數
debouncedAppendRemove(){
return debounce(function(){
if (!this.remote) {
this.modelToQuery();
this.$nextTick(() => this.broadcastQuery(''));
} else {
this.findChild((child) => {
child.updateSearchLabel(); // #1865
child.selected = this.multiple ? this.model.indexOf(child.value) > -1 : this.model === child.value;
});
}
this.slotChange();
this.updateOptions(true);
});
}
其他細節
低版本中子組件的監聽事宜沒有移撤除,高版本的有移除。
mounted () {
this.$on('on-select-close', this.onSelectClose);
this.$on('on-query-change',this.onQueryChange);
}
beforeDestroy () {
this.$off('on-select-close', this.onSelectClose);
this.$off('on-query-change',this.onQueryChange);
}