前端业务开发中不管使用vue2~3,还是react,angular各种前端技术栈,经常会遇到这种业务。一个下拉框Select中,不仅需要需要支持远程模糊搜索,还需要支持多选。并且在编辑时,还能正常把已经多选好的内容回显到Select中。
用Vue3+ElementPlus+TS举一个简单的案例。其他技术栈思路是一致的
新增时的逻辑
这一步和普通操作没有什么区别
html
<template>
<el-select
v-model="selectValue"
multiple
filterable
remote
reserve-keyword
placeholder="请搜索并选择内容"
:remote-method="remoteMethod"
style="width: 240px"
>
<el-option
v-for="item in options"
:key="item.value"
:label="`${item.value}-${item.label}`"
:value="item.value"
/>
</el-select>
</template>
ts
<script lang="ts" setup>
let selectValue = ref([]);
let options = ref<
{
value: string;
label: string;
}[]
>([]);
const remoteMethod = (value: string) => {
// 模拟远程接口查询
// 一般远程模糊搜索的接口都带分页,如果数据为10万条,模糊搜索时肯定一次不能查10万条,还是需要正产分页的
setTimeout(() => {
options.value = [
{
value: "1",
label: "张三",
},
{
value: "2",
label: "李四",
},
{
value: "3",
label: "王五",
},
];
}, 200);
};
</script>
多选OK的效果
编辑需要回显时的逻辑(关键点)
当这个下拉框在编辑页时,需要把同样已经多选的内容完整回显到这个下拉框中,因为数据本身就是多选,接口还是是分页的,回显时肯定不能使用接口查询功能来回显数据。因此,el-select的:value绑定就不应该只绑定value了。
html
<template>
<el-select
v-model="selectValue"
multiple
filterable
remote
reserve-keyword
placeholder="请搜索并选择内容"
:remote-method="remoteMethod"
style="width: 240px"
>
<!--value直接也把label绑定上-->
<el-option
v-for="item in options"
:key="item.value"
:label="`${item.value}-${item.label}`"
:value="`${item.value}-${item.label}`"
/>
</el-select>
</template>
ts
<script lang="ts" setup>
let selectValue = ref([]);
let options = ref<
{
value: string;
label: string;
}[]
>([]);
const remoteMethod = (value: string) => {};
onMounted(() => {
// 模拟编辑页初始化的时候接口初始化赋值逻辑
// 编辑页面查询到多选的详情信息data
const data = [
{
value: "1",
label: "张三",
},
{
value: "2",
label: "李四",
},
];
selectValue.value = data.map(item => `${item.value}-${item.label}`); //['1-张三', '2-李四'];
});
</script>
这时候selectValue的绑定时就不仅仅是value了,而是这样的格式。这样就不需要通过后端接口来实现多选内容的数据回显了。
json
['1-张三', '2-李四']
编辑操作时剔除label内容
当前selectValue的绑定值已经是"['1-张三', '2-李四']"这样了,编辑操作确定提交数据时剔除-label就行。
ts
const originalArray = ['1-张三', '2-李四'];
const numericArray = originalArray.map(item => {
// 使用split('-')分割字符串,并取第一个元素(即数字部分)
const numberPart = item.split('-')[0];
// 将字符串转换为数字
return parseInt(numberPart, 10);
});
console.log(numericArray); // 输出: [1, 2]。编辑确定操作时,入参给接口就行。
如果业务需求的label展示值不是
ts
:label="`${item.value}-${item.label}`"
这种形式,而是只展示名称label,不需要对应value
ts
:label="`${item.label}`"
这样的形式,有空我在把另一种思路加上。未完待续...