輸入搜索、分組展示選項、下拉選取,el-select 實現:即輸入關鍵字檢索,返回分組選項,選取跳轉到相應內容頁 —— VUE 項目-全局模糊檢索
后端數據代碼寫于下一篇:輸入搜索、分組展示選項、下拉選取,全局跳轉頁,el-select 實現 —— 后端數據處理代碼,拋磚引玉展思路
【效果圖】:分組展示選項 =>【提供界面操作體驗】

【錄制效果視頻展示】:

【流程】:
(1)讀取目標數據,如果是多個,需要多次讀取; (2)對數據進行分組,放入特定分組數據結構; (3)各分組,做相應設置; (4)數據組裝到 el-select 控件; (5)點擊選項,跳轉到相應位置。
現將關鍵代碼及結構附于下方:
1. 分組數據結構示例:
(1)標準結構示例:
groupSelectOptions2: [ { id: 1, label: '超期', options: [ { value: 'cqwbj', label: '超期未辦結' }, { value: 'ycq', label: '已超期' } ] }, { id: 2, label: '按天', options: [ { value: 't1', label: '1天' }, { value: 't2', label: '2天' }, { value: 't3', label: '3天' } ] }, { id: 3, label: '按小時', options: [ { value: 'h1', label: '1小時' }, { value: 'h2', label: '2小時' } ] } ]
(2)項目數據結構示例:
主要的就 label 和 srcPath 這兩個屬性(其余省略):label,用于顯示;srcPath,存儲選取跳轉的 url 地址。
[ { label:'', options:[ {srcPath: ''} ] }, ]
2. 封裝 el-select 成組件:
<template>
<div style="height: 15px; justify-content: center; align-items: center;">
<template>
<el-select
v-model="innerValue"
filterable
:remote="true"
:likeQuery="false"
@change="changeSelect"
:clearable="clearable"
:multiple="multiple"
:remote-method="fetchOptions"
size="small"
popper-class="productGroupSelector"
:placeholder="placeholder"
>
<el-option-group class="productGroupSelector-group" v-for="group in localOptions" :key="group.label" :label="group.label">
<div style="" v-if="multiple">
<div style="">
<el-checkbox v-model="group.checked" @change="selectAll($event, group.id)" :indeterminate="group.isIndeterminate"></el-checkbox>
</div>
<div>
<el-option
class="productGroupSelector-option"
v-for="item in group.options"
:key="item.value"
:label="item.label"
:value="item"
></el-option>
</div>
</div>
<div v-else>
<el-option
class="productGroupSelector-option"
v-for="(item,index) in group.options"
:key="index"
:label="item.label"
:value="item"
></el-option>
</div>
</el-option-group>
</el-select>
</template>
</div>
</template>
3. javascript 和 css
<script>
import $ from 'jquery';
import {getRequest} from "@/api/api";
export default {
name: 'LiloGroupSelect',
model: {
prop: 'value',
event: 'change'
},
props: {
value: {
type: [String, Array],
default: () => []
},
options: {
type: Array,
default: () => []
},
placeholder: {
type: String,
default: '請選擇'
},
multiple: {
type: Boolean,
default: false
},
clearable: {
type: Boolean,
default: false
},
collapseTags: {
type: Boolean,
default: false
},
likeQuery: {
type: Boolean,
default: false
},
searchApi: {
type: String,
default: '' // 后端搜索API地址
}
},
data() {
return {
innerValue: this.value,
inputValue: '' ,// 添加這一行來定義 inputValue
selectedOption: '',
// searchQuery: '',
filteredOptions: [],
loading: false,
allOptions: [], // 存儲所有后端返回的選項,用于篩選
localOptions: [...this.options], // 新增屬性,用于存儲當前選項
groupSelectOptions2: [
{
id: 1,
label: '超期',
options: [
{
value: 'cqwbj',
label: '超期未辦結'
},
{
value: 'ycq',
label: '已超期'
}
]
},
{
id: 2,
label: '按天',
options: [
{
value: 't1',
label: '1天'
},
{
value: 't2',
label: '2天'
}
]
},
{
id: 3,
label: '按小時',
options: [
{
value: 'h1',
label: '1小時'
},
{
value: 'h2',
label: '2小時'
}
]
}
],
isDropdownVisible: false, // 控制下拉列表的顯示狀態(默認收起)隱藏
};
},
mounted() {
this.innerValue = this.value;
this.allOptions = [...this.options, ...this.groupSelectOptions2]; // 初始化所有選項
this.filteredOptions = [...this.options]; // 初始化過濾后的選項
},
watch: {
value(newVal, odlVal) {
this.innerValue = newVal;
console.log("當前輸入值或選擇值:"+this.innerValue)
},
searchQuery(newVal) {
console.log("監聽查詢輸入:"+newVal)
this.fetchOptions(newVal);
}
},
methods: {
// 模擬后端查詢,直接返回 groupSelectOptions2
fetchOptions(queryString) {
console.log("調用后端,請求數據....查詢條件:【"+queryString+"】查詢接口為:"+this.searchApi)
if (this.loading) return;
this.loading = true;
try {
// 此處模擬為直接返回 groupSelectOptions2,實際應調用后端API
this.allOptions = [...this.options, ...this.groupSelectOptions2]; // 合并原始選項和后端返回的選項(去重應在后端處理或此處額外處理)
if(this.likeQuery) queryString = '%'+queryString+'%';
this.getRequest(this.searchApi, {query: queryString}).then(resp =>{
if (resp){
this.localOptions = [...resp];
// console.log("調用后端,返回結果:"+JSON.stringify(resp))
}
});
// this.localOptions = [...this.groupSelectOptions2]; // 更新 localOptions 而不是 this.options
// this.filteredOptions = this.filterOptionsByQuery(this.allOptions, queryString);
console.log("調用后端,數據處理結束。。。")
} catch (error) {
console.error('搜索失敗:', error);
} finally {
this.loading = false;
}
},
async query(queryString){
if(this.likeQuery) queryString = '%'+queryString+'%';
this.getRequest(this.searchApi, {query: queryString}).then(resp =>{
if (resp){
this.localOptions = [...resp];
}
});
},
filterOptionsByQuery(options, query) {
return this.allOptions.reduce((acc, group) => {
const filteredGroup = { ...group, options: group.options.filter(option => option.label.toLowerCase().includes(query.toLowerCase())) };
// const filteredGroup = { ...group, options: group.options.filter(option => option.label.includes(query)) };
if (filteredGroup.options.length > 0) {
acc.push(filteredGroup);
}
return acc;
}, []);
},
selectAll(val, id) {
const selectOption = this.options.find(f => f.id === id);
const arr = selectOption.options.map(m => m.value);
if (val) {
if((typeof this.innerValue !== 'object') || this.innerValue.constructor !== Array) {
this.innerValue = [];
}
arr.forEach(item => {
if (!this.innerValue.includes(item)) {
this.innerValue.push(item);
}
});
} else {
this.innerValue.forEach((item, index) => {
if (arr.includes(item)) {
this.innerValue.splice(index, 1, '');
}
});
}
this.innerValue = this.innerValue.filter(f => f !== '');
if (selectOption.checked) {
selectOption.isIndeterminate = false;
}
this.$emit('change', this.innerValue);
},
changeSelect(val) {
console.log("選項變更值:"+val)
if (this.multiple) {
this.options.forEach(item => {
const arr = item.options.map(m => m.value);
item.isIndeterminate = arr.some(v => {
return val.some(s => s === v);
});
item.checked = arr.every(v => {
return val.some(s => s === v);
});
if (item.checked) {
item.isIndeterminate = false;
}
});
this.$emit('change', this.innerValue);
} else {
this.$emit('change', val);
}
},
}
};
</script>
<style>
.productGroupSelector {
min-width: initial !important;
width: 415px;
}
</style>
<style lang="scss" scoped>
::v-deep {
.el-select-group {
width: 400px;
display: flex;
flex-wrap: wrap;
justify-content: start;
padding: 0px 10px;
}
.el-select-group__title {
padding-left: 20px;
font-size: 12px;
}
}
.productGroupSelector-group {
padding-top: 5px;
display: flex;
// align-items: center;
// flex-wrap: wrap;
// width: 400px;
padding-bottom: 5px;
flex-direction: column;
margin: 0 5px;
// &:not(:last-child) {
// border-bottom: 1px solid rgba($color: #000000, $alpha: 0.1);
// }
&::after {
display: none;
}
}
.productGroupSelector-option {
display: inline-flex;
align-items: center;
flex-wrap: wrap;
}
// .productGroupSelector {
// .el-scrollbar__view .el-select-dropdown__list {
// display: flex;
// flex-wrap: wrap;
// justify-content: space-between;
// align-items: baseline;
// padding-top: 0;
// overflow-x: hidden;
// }
// .el-select-dropdown__wrap .el-scrollbar__wrap {
// max-height: 650px;
// }
// }
</style>
4. 引用 LiloGroupSelect
<el-row :gutter="20" style="display: flex; border-radius: 5px;" >
<el-col style="margin-bottom: 7px;">
<lilo-group-select @change="groupSelectChange" :multiple="false" :likeQuery="true" :searchApi="'/api/list/search'" clearable placeholder="請輸入快速搜索" ></lilo-group-select>
</el-col>
</el-row>
<script>
import LiloGroupSelect from "@/components/common/help/ElementUIGroupSelect";
export default {
name: "***",
components: {
LiloGroupSelect
},
data(){
return{}
},
methods: {
groupSelectChange(option) {
console.log("下拉選項選中:"+JSON.stringify(option));
if(option==''|| option.srcPath=='')return;
// this.$router.push(option.srcPath);
this.$router.push(option.srcPath).catch(err => {
if (err.name !== 'NavigationDuplicated') {
// 處理其他可能的錯誤
console.error(err);
}
// 對于 NavigationDuplicated 錯誤,可以選擇不做任何處理
});
},
}
}
【效果圖】:分組展示選項

參考資源:
1. Vue【原創】基于elementui的【分組多選下拉框group-select】 2. el-select選擇器組件封裝 下拉菜單 elementui 3. Vue Element 分組+多選+可搜索Select選擇器實現示例 4. 基于Vue和Element-UI自定義分組以及分組全選Select 選擇器
【項目實際效果】: 便捷簡潔的企業官網
后端數據代碼寫于下一篇:輸入搜索、分組展示選項、下拉選取,全局跳轉頁,el-select 實現 —— 后端數據處理代碼,拋磚引玉展思路
————————————————
本文同步發表于:https://blog.csdn.net/wangqingbo0829/article/details/131487939
浙公網安備 33010602011771號