最近遇到一個下拉框選項過多導致頁面太卡甚至卡死的問題,搜了一下懶加載以及遠程搜索方法,整理了一下:
1、el-select懶加載
el-select選擇器里的數據通過后端返回得到,這里返回了將近兩萬條數據,點開選擇器頁面就特別卡,所以最好采用懶加載方法,具體使用如下:
控件部分:
<el-select
v-model="form"
placeholder=""
v-el-select-loadmore="loadmore" //懶加載方法
>
<el-option
v-for="item in dataItems"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
數據部分:
form: {},
allData: [], //存放下拉框全部數據
dataItems: [], //下拉框顯示的數據
pageData: { //懶加載相關參數,這里代表從第一條數據開始加載,一次加載二十項
pageIndex: 1,
pageSize: 20
},
方法部分:
directives: {
/** 下拉框懶加載 */
'el-select-loadmore': {
bind(el, binding) {
const SELECTWRAP_DOM = el.querySelector(
'.el-select-dropdown .el-select-dropdown__wrap'
);
SELECTWRAP_DOM.addEventListener('scroll', function() {
const condition =
this.scrollHeight - this.scrollTop <= this.clientHeight;
if (condition) {
binding.value();
}
});
}
}
},
methods: {
/** 下拉框懶加載 */
loadmore() {
this.pageData.pageIndex++;
this.getItems(this.pageData); //類似於分頁查詢
},
/** 一次加載二十條證券代碼 */
getItems(value) {
let num = ~~this.pageData.pageIndex * ~~this.pageData.pageSize;
this.dataItems = this.allData.filter((item, index, arr) => {
return index < num; //這里默認allData已經取到了數據,就不把獲取allData數據的方法放上來了
});
},
}
這樣就實現了el-select下拉框數據的懶加載,注意:
如果和我一樣下拉框里的選項(比如這里的allData)是動態變化的,在每次獲取新的數據之后要把pageData里的數據還原,即在獲取數據的方法里加上這兩句:
this.pageData.pageIndex = 1;
this.pageData.pageSize = 20;
否則每次獲取完新的數據之后只是從上一次加載到的地方開始加載,而不是重新從第一條開始每次加載二十條。
2、下拉框選項可搜索
由於我在實際使用的時候下拉框有接近兩萬條數據,出於需求考慮,不可能把所有數據全部加載一遍再選擇,所以還需要有搜索功能,只要在上面代碼的基礎上加上:
控件部分,el-select改為:
<el-select
v-model="form"
placeholder=""
filterable //表示數據可搜索
:filter-method="dataFilter" //搜索的方法
default-first-option //在輸入框按下回車,選擇第一個匹配項,配合 filterable使用
v-el-select-loadmore="loadmore"
>
方法部分,添加dataFilter方法:
/** 下拉框搜索 */
dataFilter(val) {
if (val) { //val存在
this.dataItems = this.allData.filter((item) => {
if (!!~item.value.indexOf(val)) { //這里匹配的是選項的value,也可以改成label
return true
}
})
} else { //val為空時,還原數組
this.getItems(this.pageData);
}
},
3、遠程搜索
但是在使用過程中發現上面的方法還是有點卡,所以再嘗試了一下遠程搜索的方法,在一開始不把所有選項展示出來,並且去掉懶加載,輸入關鍵字之后再去匹配選項的value值,顯示出匹配的選項:
控件部分,el-select改為:
<el-select
v-model="form"
clearable
filterable
remote //表示遠程搜索
:remote-method="remoteMethod" //遠程搜索方法
>
方法部分,添加remoteMethod方法:
remoteMethod(query) {
if (query !== '') {
setTimeout(() => {
this.dataItems = this.allData.filter(item => {
return item.value.toLowerCase() //這里同樣是匹配選項的value
.indexOf(query.toLowerCase()) > -1;
});
}, 200);
} else {
this.dataItems = [];
}
},
嘗試之后發現遠程搜索會比懶加載+直接搜索渲染得更快一些,所以最終采用的是遠程搜索方法