vue实现左右多选框
Vue 实现左右多选框组件
左右多选框(Transfer)是常见的表单组件,用于在两个列表之间移动选项。以下是基于 Vue 2/3 的实现方法:
基础组件结构
<template>
<div class="transfer-container">
<div class="transfer-panel">
<h3>可选列表</h3>
<ul>
<li v-for="item in leftItems" :key="item.value">
<input type="checkbox" v-model="selectedLeft" :value="item.value">
{{ item.label }}
</li>
</ul>
</div>
<div class="transfer-actions">
<button @click="moveToRight">→</button>
<button @click="moveToLeft">←</button>
</div>
<div class="transfer-panel">
<h3>已选列表</h3>
<ul>
<li v-for="item in rightItems" :key="item.value">
<input type="checkbox" v-model="selectedRight" :value="item.value">
{{ item.label }}
</li>
</ul>
</div>
</div>
</template>
核心逻辑实现
<script>
export default {
data() {
return {
leftItems: [
{ value: 1, label: '选项1' },
{ value: 2, label: '选项2' },
{ value: 3, label: '选项3' }
],
rightItems: [],
selectedLeft: [],
selectedRight: []
}
},
methods: {
moveToRight() {
const movedItems = this.leftItems.filter(item =>
this.selectedLeft.includes(item.value)
)
this.rightItems = [...this.rightItems, ...movedItems]
this.leftItems = this.leftItems.filter(item =>
!this.selectedLeft.includes(item.value)
)
this.selectedLeft = []
},
moveToLeft() {
const movedItems = this.rightItems.filter(item =>
this.selectedRight.includes(item.value)
)
this.leftItems = [...this.leftItems, ...movedItems]
this.rightItems = this.rightItems.filter(item =>
!this.selectedRight.includes(item.value)
)
this.selectedRight = []
}
}
}
</script>
样式优化
<style scoped>
.transfer-container {
display: flex;
align-items: center;
gap: 20px;
}
.transfer-panel {
border: 1px solid #ddd;
width: 200px;
height: 300px;
overflow-y: auto;
}
.transfer-actions {
display: flex;
flex-direction: column;
gap: 10px;
}
ul {
list-style: none;
padding: 0;
}
li {
padding: 8px;
border-bottom: 1px solid #eee;
}
</style>
进阶功能实现
双向绑定支持
props: {
value: {
type: Array,
default: () => []
}
},
watch: {
value(newVal) {
this.rightItems = newVal
this.leftItems = this.allItems.filter(item =>
!newVal.some(v => v.value === item.value)
)
},
rightItems: {
handler(newVal) {
this.$emit('input', newVal)
},
deep: true
}
}
全选功能
methods: {
selectAllLeft() {
this.selectedLeft = this.leftItems.map(item => item.value)
},
selectAllRight() {
this.selectedRight = this.rightItems.map(item => item.value)
}
}
搜索过滤
<input v-model="leftFilter" placeholder="搜索">
<ul>
<li v-for="item in filteredLeftItems" :key="item.value">
<!-- 选项内容 -->
</li>
</ul>
computed: {
filteredLeftItems() {
return this.leftItems.filter(item =>
item.label.includes(this.leftFilter)
)
}
}
使用第三方库
对于生产环境,推荐使用成熟的组件库:
- Element UI 的
el-transfer - Ant Design Vue 的
a-transfer - Vuetify 的
v-combobox配合多选模式
这些库提供了更完善的API和样式,例如:
<el-transfer
v-model="value"
:data="data"
:titles="['Source', 'Target']"
></el-transfer>
实现时需注意性能优化,特别是大数据量场景下应考虑虚拟滚动、分页加载等技术方案。







