淺談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ù),對我們來說也支持一個變量,占個內(nèi)存。當然數(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方法進行搜索過濾,在搜索時用過濾結(jié)果更新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內(nèi) 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頭部
到此這篇關(guān)于ElementUI el-select 數(shù)據(jù)過多解決辦法的文章就介紹到這了,更多相關(guān)ElementUI el-select 數(shù)據(jù)過多內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue中@click.stop與@click.prevent、@click.native使用
這篇文章主要介紹了Vue中@click.stop與@click.prevent、@click.native使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08SpringBoot結(jié)合Vue3實現(xiàn)簡單的前后端交互
本文主要介紹了SpringBoot結(jié)合Vue3實現(xiàn)簡單的前后端交互,結(jié)合實際案例,說明了如何實現(xiàn)前后端數(shù)據(jù)的交互,具有一定的?參考價值,感興趣的可以了解一下2023-08-08vue3+element-plus props中的變量使用 v-model 報錯及解決方案
這篇文章主要介紹了vue3+element-plus props中的變量使用 v-model 報錯及解決方案,prop 是單向數(shù)據(jù)流,這里只能用:model-value,不能用v-model,本文給大家介紹的非常詳細,需要的朋友可以參考下2023-10-10vue3+ts+Vuex中使用websocket協(xié)議方式
這篇文章主要介紹了vue3+ts+Vuex中使用websocket協(xié)議方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10