vue穿梭框组件实现
实现 Vue 穿梭框组件的基本思路
穿梭框(Transfer)组件通常用于在两个列表之间移动数据项。核心功能包括左侧列表、右侧列表、移动按钮(左移、右移、全选等)以及数据项的渲染与交互。
基础结构设计
创建 Transfer.vue 文件,定义组件的基本结构:

<template>
<div class="transfer-container">
<div class="transfer-list left-list">
<h3>左侧列表</h3>
<ul>
<li v-for="item in leftItems" :key="item.id">
<input type="checkbox" v-model="item.checked" />
{{ item.label }}
</li>
</ul>
</div>
<div class="transfer-buttons">
<button @click="moveToRight">→</button>
<button @click="moveToLeft">←</button>
</div>
<div class="transfer-list right-list">
<h3>右侧列表</h3>
<ul>
<li v-for="item in rightItems" :key="item.id">
<input type="checkbox" v-model="item.checked" />
{{ item.label }}
</li>
</ul>
</div>
</div>
</template>
数据模型与逻辑
定义组件的数据模型和核心方法:

<script>
export default {
props: {
data: {
type: Array,
default: () => [],
},
},
data() {
return {
leftItems: [],
rightItems: [],
};
},
methods: {
moveToRight() {
const selectedItems = this.leftItems.filter((item) => item.checked);
this.rightItems = [...this.rightItems, ...selectedItems];
this.leftItems = this.leftItems.filter((item) => !item.checked);
},
moveToLeft() {
const selectedItems = this.rightItems.filter((item) => item.checked);
this.leftItems = [...this.leftItems, ...selectedItems];
this.rightItems = this.rightItems.filter((item) => !item.checked);
},
},
created() {
this.leftItems = this.data.map((item) => ({
...item,
checked: false,
}));
},
};
</script>
样式优化
添加基础样式增强交互体验:
<style scoped>
.transfer-container {
display: flex;
align-items: center;
gap: 20px;
}
.transfer-list {
border: 1px solid #ddd;
width: 200px;
height: 300px;
overflow-y: auto;
padding: 10px;
}
.transfer-buttons {
display: flex;
flex-direction: column;
gap: 10px;
}
ul {
list-style: none;
padding: 0;
}
li {
padding: 5px;
cursor: pointer;
}
li:hover {
background-color: #f5f5f5;
}
</style>
功能扩展
- 全选/反选功能
添加全选按钮,快速选择所有项目:
methods: {
toggleAllLeft(selectAll) {
this.leftItems.forEach(item => {
item.checked = selectAll;
});
},
toggleAllRight(selectAll) {
this.rightItems.forEach(item => {
item.checked = selectAll;
});
},
}
- 搜索过滤
增加搜索框过滤列表项:
<div class="transfer-list left-list">
<input v-model="leftSearch" placeholder="搜索..." />
<ul>
<li v-for="item in filteredLeftItems" :key="item.id">
<!-- 省略 -->
</li>
</ul>
</div>
computed: {
filteredLeftItems() {
return this.leftItems.filter(item =>
item.label.includes(this.leftSearch)
);
},
}
- 拖拽支持
通过draggable属性实现拖拽移动:
<li
draggable="true"
@dragstart="handleDragStart(item, 'left')"
@drop="handleDrop('right')"
@dragover.prevent
>
<!-- 省略 -->
</li>
使用示例
在父组件中调用:
<Transfer :data="[
{ id: 1, label: '选项1' },
{ id: 2, label: '选项2' },
{ id: 3, label: '选项3' },
]" />
注意事项
- 数据项需包含唯一标识(如
id)和显示文本(如label)。 - 可通过插槽(slot)自定义列表项的渲染方式。
- 对于大量数据,建议使用虚拟滚动优化性能。






