vue实现穿梭框
Vue 实现穿梭框组件
穿梭框(Transfer)是一种常见的UI组件,用于在两栏之间移动元素。以下是基于Vue的实现方法:
基本结构实现
创建两个列表容器和操作按钮区域:
<template>
<div class="transfer-container">
<div class="transfer-list">
<h3>源列表</h3>
<ul>
<li v-for="item in sourceList" :key="item.id">
<input type="checkbox" v-model="selectedSource" :value="item.id">
{{ item.label }}
</li>
</ul>
</div>
<div class="transfer-actions">
<button @click="moveToTarget">→</button>
<button @click="moveToSource">←</button>
</div>
<div class="transfer-list">
<h3>目标列表</h3>
<ul>
<li v-for="item in targetList" :key="item.id">
<input type="checkbox" v-model="selectedTarget" :value="item.id">
{{ item.label }}
</li>
</ul>
</div>
</div>
</template>
数据与逻辑处理
<script>
export default {
data() {
return {
sourceList: [
{ id: 1, label: '选项1' },
{ id: 2, label: '选项2' },
{ id: 3, label: '选项3' }
],
targetList: [],
selectedSource: [],
selectedTarget: []
}
},
methods: {
moveToTarget() {
this.selectedSource.forEach(id => {
const index = this.sourceList.findIndex(item => item.id === id)
if (index !== -1) {
this.targetList.push(this.sourceList[index])
this.sourceList.splice(index, 1)
}
})
this.selectedSource = []
},
moveToSource() {
this.selectedTarget.forEach(id => {
const index = this.targetList.findIndex(item => item.id === id)
if (index !== -1) {
this.sourceList.push(this.targetList[index])
this.targetList.splice(index, 1)
}
})
this.selectedTarget = []
}
}
}
</script>
样式优化
<style>
.transfer-container {
display: flex;
align-items: center;
gap: 20px;
}
.transfer-list {
border: 1px solid #ddd;
width: 200px;
height: 300px;
overflow-y: auto;
}
.transfer-list ul {
list-style: none;
padding: 0;
margin: 0;
}
.transfer-list li {
padding: 8px;
border-bottom: 1px solid #eee;
}
.transfer-actions {
display: flex;
flex-direction: column;
gap: 10px;
}
.transfer-actions button {
padding: 5px 10px;
cursor: pointer;
}
</style>
高级功能扩展
-
搜索过滤功能:
computed: { filteredSourceList() { return this.sourceList.filter(item => item.label.toLowerCase().includes(this.sourceSearch.toLowerCase()) ) }, filteredTargetList() { return this.targetList.filter(item => item.label.toLowerCase().includes(this.targetSearch.toLowerCase()) ) } } -
全选功能:

methods: { selectAllSource() { this.selectedSource = this.filteredSourceList.map(item => item.id) }, selectAllTarget() { this.selectedTarget = this.filteredTargetList.map(item => item.id) } } -
拖拽排序支持:
<li v-for="item in targetList" :key="item.id" draggable="true" @dragstart="dragStart(item)" @dragover.prevent @drop="dropOnTarget($event, item)" >
组件封装建议
-
通过props接收初始数据:

props: { data: { type: Array, default: () => [] }, value: { type: Array, default: () => [] } } -
使用v-model实现双向绑定:
watch: { targetList(newVal) { this.$emit('input', newVal) } } -
提供插槽自定义渲染:
<slot name="item" v-bind="{ item }"> {{ item.label }} </slot>
使用第三方库
对于生产环境,可以考虑使用成熟的UI库:
- Element UI的Transfer组件
- Ant Design Vue的Transfer组件
- Vuetify的v-data-iterator实现类似功能
这些库提供了更完善的API和样式,可以直接集成使用。






