vue 实现多选功能
Vue 多选功能实现方法
基础实现(v-model 绑定数组)
通过 v-model 绑定数组实现多选,适用于原生 <select multiple> 或复选框组:
<template>
<!-- 原生多选下拉框 -->
<select v-model="selectedItems" multiple>
<option v-for="item in options" :value="item.value">{{ item.label }}</option>
</select>
<!-- 复选框组 -->
<div v-for="item in options" :key="item.value">
<input
type="checkbox"
:id="item.value"
:value="item.value"
v-model="selectedItems"
>
<label :for="item.value">{{ item.label }}</label>
</div>
</template>
<script>
export default {
data() {
return {
selectedItems: [],
options: [
{ value: 'opt1', label: 'Option 1' },
{ value: 'opt2', label: 'Option 2' }
]
}
}
}
</script>
自定义组件实现
封装可复用的多选组件,支持搜索、标签展示等功能:
<template>
<div class="multi-select">
<div class="selected-tags">
<span v-for="(item, index) in selected" :key="index">
{{ getLabel(item) }}
<button @click="removeItem(index)">×</button>
</span>
</div>
<input
type="text"
v-model="searchText"
@keydown.enter="addItem"
placeholder="Type and press Enter"
>
<ul v-if="filteredOptions.length">
<li
v-for="item in filteredOptions"
:key="item.value"
@click="toggleItem(item.value)"
>
{{ item.label }}
</li>
</ul>
</div>
</template>
<script>
export default {
props: {
options: Array,
value: Array
},
data() {
return {
searchText: '',
selected: this.value || []
}
},
computed: {
filteredOptions() {
return this.options.filter(opt =>
!this.selected.includes(opt.value) &&
opt.label.toLowerCase().includes(this.searchText.toLowerCase())
)
}
},
methods: {
toggleItem(value) {
const index = this.selected.indexOf(value)
if (index > -1) {
this.selected.splice(index, 1)
} else {
this.selected.push(value)
}
this.$emit('input', [...this.selected])
},
getLabel(value) {
const item = this.options.find(opt => opt.value === value)
return item ? item.label : value
},
removeItem(index) {
this.selected.splice(index, 1)
this.$emit('input', [...this.selected])
}
}
}
</script>
第三方库方案
使用现成的多选组件库(如 vue-multiselect):

-
安装依赖:
npm install vue-multiselect -
基础用法:

<template> <multiselect v-model="selected" :options="options" :multiple="true" :close-on-select="false" label="label" track-by="value" ></multiselect> </template>
高级功能扩展
实现全选/反选、分组显示等高级功能:
<template>
<div>
<button @click="toggleAll">Toggle All</button>
<div v-for="group in groupedOptions" :key="group.name">
<h4>{{ group.name }}</h4>
<label v-for="item in group.items" :key="item.value">
<input
type="checkbox"
:value="item.value"
v-model="selectedItems"
>
{{ item.label }}
</label>
</div>
</div>
</template>
<script>
export default {
data() {
return {
selectedItems: [],
groupedOptions: [
{
name: 'Group A',
items: [
{ value: 'a1', label: 'Item A1' },
{ value: 'a2', label: 'Item A2' }
]
},
{
name: 'Group B',
items: [
{ value: 'b1', label: 'Item B1' },
{ value: 'b2', label: 'Item B2' }
]
}
]
}
},
methods: {
toggleAll() {
const allValues = this.groupedOptions.flatMap(g => g.items.map(i => i.value))
this.selectedItems = this.selectedItems.length === allValues.length
? []
: [...allValues]
}
}
}
</script>
性能优化建议
对于大型数据集(1000+项),建议:
- 添加虚拟滚动(使用
vue-virtual-scroller) - 实现分页加载
- 添加防抖搜索(使用 Lodash 的
debounce) - 避免在模板中使用复杂计算






