淺談ElementUI el-select 數(shù)據(jù)過多解決辦法
1. 場景描述
不知道你有沒有這樣的經(jīng)歷,下拉框的選項很多,上萬個選項甚至更多,這個時候如果全部把數(shù)據(jù)放到下拉框中渲染出來,瀏覽器會卡死,體驗會特別不好
用人會說element-ui的select有一個remote-method,支持遠程搜索,我們讓服務端支持一下不就可以了,當然這是一種解決的方案。但是有時候這種方法有時候不一定適用
(1)有時候服務端數(shù)據(jù)是經(jīng)過計算返回給我們的,可能返回不是特別快,體驗不是很好
(2)有時候數(shù)據(jù)可能只有幾千條,全部渲染又不太合適,一直掉接口不是特別好
(3)僅僅通過前端能不能解決,如果能解決,豈不是減輕了服務端的工作和壓力
2.解決辦法
1 ) 分段加載:也不加載下拉項,通過點擊下拉框的時候,再去加載,此時的選項全部加載進來,該種情況只適用于緩加載情況,需要點擊加載完后才能下拉選項,體驗一般。
2 )提示:element-ui的select有一個filter-method方法,我們可以通過這個方法來進行過濾下拉項
假設我們有個下拉框是用來選擇用戶的
<el-select
v-model="userId"
filterable
:filter-method="userFilter"
clearable>
<el-option
v-for="item in userList"
:key="item.userId"
:label="item.username"
:value="item.userId"
></el-option>
</el-select>
userFilter(query = '') {
let arr = this.allUserList.filter((item) => {
return item.username.includes(query) || item.userId.includes(query)
})
if (arr.length > 50) {
this.userList = arr.slice(0, 50)
} else {
this.userList = arr
}
},
getUserWhiteList() {
HttpRequest.post("/api/admin/community/getUserWhiteList").then(
response => {
this.allUserList = response.data.list;
this.userFilter()
}
);
},
如上所示,我們從后臺獲取用戶列表,經(jīng)過我們自己的過濾,我們每次只渲染50條數(shù)據(jù),無論有多少數(shù)據(jù),對我們來說也支持一個變量,占個內存。當然數(shù)據(jù)越多,數(shù)組的遍歷也會相應的慢,但是這個影響不大。
我們不僅能過濾名字,還可以對我們制定的任一項進行過濾
優(yōu)化:上面的代碼我們還可以適當優(yōu)化下,只有發(fā)現(xiàn)了數(shù)組長度超過了50項,我們就停止遍歷
el-select組件的options條數(shù)過多時的解決方案
業(yè)務場景
當使用el-select組件時,如果options數(shù)量過多,會存在的弊端:
頁面渲染出大量el-option節(jié)點,會導致頁面卡頓甚至卡死,用戶體驗極差。
選擇時條目眾多,查找困難。
本次我遇到的場景是options數(shù)量為6-9千的情況。
解決思路
從總options中取出固定條目的小option(renderOption)用于頁面渲染,利用el-select提供的
filter-method方法進行搜索過濾,在搜索時用過濾結果更新renderOption。
代碼實現(xiàn)
下面是vue的組件封裝
<template>
<el-select
class="yt-select"
v-model="currValue"
filterable
v-bind="$attrs"
:filter-method="userFilter"
:disabled="disabled"
:clearable="clearable"
@change="change"
>
<el-option
v-for="option in renderOption"
:key="option.value"
:value="option.value"
:label="option.label"
>{{ option.label }}</el-option>
</el-select>
</template>
<script>
export default {
name: 'easy-select',
props: {
value: {
type: [String, Number],
default: ''
},
max: {
type: Number,
default: 30
},
disabled: {
type: Boolean,
default: false
},
clearable: {
type: Boolean,
default: true
},
options: {
type: Array,
default: () => []
}
},
data () {
return {
renderOption: []
}
},
computed: {
currValue: {
get () {
return this.value || ''
},
set (value) {
this.$emit('input', value)
}
}
},
watch: {
value () {
this.addValueOptions()
},
options: {
handler (V) {
this.init()
},
deep: true
}
},
created () {
this.init()
},
methods: {
async init () {
this.userFilter()
this.addValueOptions()
},
addValueOptions () {
if (this.currValue) {
let target = this.options.find((item) => { // 從大option中找到當前條
return item.value === this.currValue
})
if (target) { // 將當前條與小option比對,沒有則加入
if (this.renderOption.every(item => item.value !== target.value)) {
this.renderOption.unshift(target)
}
}
}
},
addFilterOptions (label) {
// 每次查找輸入時,若有精確匹配的條目,保證該條目一定在renderOption內
let target = this.options.find((item) => { // 從大option中找到當前條
return item.label === label
})
if (target) { // 將當前條與小option比對,沒有則加入
if (this.renderOption.every(item => item.label !== target.label)) {
this.renderOption.unshift(target)
}
}
},
userFilter (query = '') {
let arr = this.options.filter((item) => {
return item.label.includes(query) || item.value.includes(query)
})
if (arr.length > this.max) {
this.renderOption = arr.slice(0, this.max)
this.addFilterOptions(query)
} else {
this.renderOption = arr
}
},
change (value) {
this.$emit('change', value)
if (!value) { // 單選清空-optons初始化下
this.userFilter()
}
}
}
}
</script>
注意事項
- 初始化和value值變化時,需要找到value對應具體項,并加入renderOptions
- 搜索時,可能過濾到的n條數(shù)據(jù)都沒有包含用戶想找的具體項,因此,過濾時需要進行一下精確查找,將匹配項放入renderOptions頭部
到此這篇關于ElementUI el-select 數(shù)據(jù)過多解決辦法的文章就介紹到這了,更多相關ElementUI el-select 數(shù)據(jù)過多內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Vue實現(xiàn)視頻播放vue-video-player、dplayer方式
這篇文章主要介紹了Vue實現(xiàn)視頻播放vue-video-player、dplayer方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-04-04
vue2.0s中eventBus實現(xiàn)兄弟組件通信的示例代碼
這篇文章主要介紹了vue2.0s中eventBus實現(xiàn)兄弟組件通信的示例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10
axios 實現(xiàn)post請求時把對象obj數(shù)據(jù)轉為formdata
今天小編就為大家分享一篇axios 實現(xiàn)post請求時把對象obj數(shù)據(jù)轉為formdata,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10

