淺談ElementUI el-select 數(shù)據(jù)過多解決辦法
1. 場(chǎng)景描述
不知道你有沒有這樣的經(jīng)歷,下拉框的選項(xiàng)很多,上萬個(gè)選項(xiàng)甚至更多,這個(gè)時(shí)候如果全部把數(shù)據(jù)放到下拉框中渲染出來,瀏覽器會(huì)卡死,體驗(yàn)會(huì)特別不好
用人會(huì)說element-ui的select有一個(gè)remote-method,支持遠(yuǎn)程搜索,我們讓服務(wù)端支持一下不就可以了,當(dāng)然這是一種解決的方案。但是有時(shí)候這種方法有時(shí)候不一定適用
(1)有時(shí)候服務(wù)端數(shù)據(jù)是經(jīng)過計(jì)算返回給我們的,可能返回不是特別快,體驗(yàn)不是很好
(2)有時(shí)候數(shù)據(jù)可能只有幾千條,全部渲染又不太合適,一直掉接口不是特別好
(3)僅僅通過前端能不能解決,如果能解決,豈不是減輕了服務(wù)端的工作和壓力
2.解決辦法
1 ) 分段加載:也不加載下拉項(xiàng),通過點(diǎn)擊下拉框的時(shí)候,再去加載,此時(shí)的選項(xiàng)全部加載進(jìn)來,該種情況只適用于緩加載情況,需要點(diǎn)擊加載完后才能下拉選項(xiàng),體驗(yàn)一般。
2 )提示:element-ui的select有一個(gè)filter-method方法,我們可以通過這個(gè)方法來進(jìn)行過濾下拉項(xiàng)
假設(shè)我們有個(gè)下拉框是用來選擇用戶的
<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()
}
);
},
如上所示,我們從后臺(tái)獲取用戶列表,經(jīng)過我們自己的過濾,我們每次只渲染50條數(shù)據(jù),無論有多少數(shù)據(jù),對(duì)我們來說也支持一個(gè)變量,占個(gè)內(nèi)存。當(dāng)然數(shù)據(jù)越多,數(shù)組的遍歷也會(huì)相應(yīng)的慢,但是這個(gè)影響不大。
我們不僅能過濾名字,還可以對(duì)我們制定的任一項(xiàng)進(jìn)行過濾
優(yōu)化:上面的代碼我們還可以適當(dāng)優(yōu)化下,只有發(fā)現(xiàn)了數(shù)組長度超過了50項(xiàng),我們就停止遍歷
el-select組件的options條數(shù)過多時(shí)的解決方案
業(yè)務(wù)場(chǎng)景
當(dāng)使用el-select組件時(shí),如果options數(shù)量過多,會(huì)存在的弊端:
頁面渲染出大量el-option節(jié)點(diǎn),會(huì)導(dǎo)致頁面卡頓甚至卡死,用戶體驗(yàn)極差。
選擇時(shí)條目眾多,查找困難。
本次我遇到的場(chǎng)景是options數(shù)量為6-9千的情況。
解決思路
從總options中取出固定條目的小option(renderOption)用于頁面渲染,利用el-select提供的
filter-method方法進(jìn)行搜索過濾,在搜索時(shí)用過濾結(jié)果更新renderOption。
代碼實(shí)現(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中找到當(dāng)前條
return item.value === this.currValue
})
if (target) { // 將當(dāng)前條與小option比對(duì),沒有則加入
if (this.renderOption.every(item => item.value !== target.value)) {
this.renderOption.unshift(target)
}
}
}
},
addFilterOptions (label) {
// 每次查找輸入時(shí),若有精確匹配的條目,保證該條目一定在renderOption內(nèi)
let target = this.options.find((item) => { // 從大option中找到當(dāng)前條
return item.label === label
})
if (target) { // 將當(dāng)前條與小option比對(duì),沒有則加入
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>
注意事項(xiàng)
- 初始化和value值變化時(shí),需要找到value對(duì)應(yīng)具體項(xiàng),并加入renderOptions
- 搜索時(shí),可能過濾到的n條數(shù)據(jù)都沒有包含用戶想找的具體項(xiàng),因此,過濾時(shí)需要進(jìn)行一下精確查找,將匹配項(xiàng)放入renderOptions頭部
到此這篇關(guān)于ElementUI el-select 數(shù)據(jù)過多解決辦法的文章就介紹到這了,更多相關(guān)ElementUI el-select 數(shù)據(jù)過多內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue中@click.stop與@click.prevent、@click.native使用
這篇文章主要介紹了Vue中@click.stop與@click.prevent、@click.native使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
vue router點(diǎn)擊打開新的標(biāo)簽頁的方法(最新推薦)
vue router點(diǎn)擊打開新的標(biāo)簽頁的方法,只需要在router-link中加入target="_blank"即可在新的頁面打開標(biāo)簽,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-10-10
SpringBoot結(jié)合Vue3實(shí)現(xiàn)簡單的前后端交互
本文主要介紹了SpringBoot結(jié)合Vue3實(shí)現(xiàn)簡單的前后端交互,結(jié)合實(shí)際案例,說明了如何實(shí)現(xiàn)前后端數(shù)據(jù)的交互,具有一定的?參考價(jià)值,感興趣的可以了解一下2023-08-08
vue 做移動(dòng)端微信公眾號(hào)采坑經(jīng)驗(yàn)記錄
這篇文章主要介紹了vue 做移動(dòng)端微信公眾號(hào)采坑經(jīng)驗(yàn)記錄,文中是小編記錄的三個(gè)坑及解決方案,需要的朋友可以參考下2018-04-04
vue3+element-plus props中的變量使用 v-model 報(bào)錯(cuò)及解決方案
這篇文章主要介紹了vue3+element-plus props中的變量使用 v-model 報(bào)錯(cuò)及解決方案,prop 是單向數(shù)據(jù)流,這里只能用:model-value,不能用v-model,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10
vue3+ts+Vuex中使用websocket協(xié)議方式
這篇文章主要介紹了vue3+ts+Vuex中使用websocket協(xié)議方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10

