vue实现树穿梭
Vue实现树形穿梭框方案
使用Element UI的Tree和Transfer组件结合实现树形穿梭功能。需要安装Element UI库,版本建议2.15.x以上。
npm install element-ui -S
基础组件结构
在Vue文件中引入必要组件并构建基础模板结构。需要同时使用el-tree和el-transfer组件,通过自定义渲染实现树形展示。
<template>
<div class="tree-transfer">
<el-transfer
v-model="selectedKeys"
:data="transferData"
:titles="['源数据', '已选择']"
:props="{ key: 'id', label: 'label' }"
:left-default-checked="leftChecked"
:right-default-checked="rightChecked">
<template #left-footer>
<el-tree
ref="sourceTree"
:data="treeData"
show-checkbox
node-key="id"
:props="treeProps"
@check-change="handleCheckChange">
</el-tree>
</template>
</el-transfer>
</div>
</template>
数据处理逻辑
准备树形数据和平面化处理,确保穿梭框能正确显示树形结构。需要将树形数据转换为Transfer组件可识别的平面数据结构。
export default {
data() {
return {
treeData: [
{
id: 1,
label: '一级节点',
children: [
{ id: 4, label: '二级节点-1' },
{ id: 5, label: '二级节点-2' }
]
}
],
transferData: [],
selectedKeys: [],
leftChecked: [],
rightChecked: [],
treeProps: {
label: 'label',
children: 'children'
}
}
},
methods: {
flattenTree(tree, arr = []) {
tree.forEach(node => {
arr.push({ id: node.id, label: node.label })
if (node.children) {
this.flattenTree(node.children, arr)
}
})
return arr
}
},
mounted() {
this.transferData = this.flattenTree(this.treeData)
}
}
选中状态同步
处理Tree组件和Transfer组件之间的选中状态同步。当树节点被勾选时,需要更新Transfer组件的选中状态。
methods: {
handleCheckChange(node, checked) {
const checkedKeys = this.$refs.sourceTree.getCheckedKeys()
this.leftChecked = checkedKeys.filter(key => !this.selectedKeys.includes(key))
if (checked) {
if (!this.selectedKeys.includes(node.id)) {
this.selectedKeys.push(node.id)
}
} else {
this.selectedKeys = this.selectedKeys.filter(key => key !== node.id)
}
}
}
样式优化
添加CSS样式改善显示效果,确保树形结构和穿梭框布局协调。需要特别注意高度控制和滚动条处理。
.tree-transfer {
display: flex;
justify-content: center;
}
.el-transfer {
width: 800px;
}
.el-tree {
height: 400px;
overflow: auto;
margin-top: 10px;
}
完整组件封装
将上述逻辑封装为可复用的TreeTransfer组件,支持自定义节点渲染和外部数据绑定。
export default {
props: {
data: {
type: Array,
required: true
},
value: {
type: Array,
default: () => []
}
},
watch: {
value(newVal) {
this.selectedKeys = [...newVal]
},
selectedKeys(newVal) {
this.$emit('input', [...newVal])
}
}
}
性能优化建议
对于大型树结构,建议采用懒加载和虚拟滚动技术。可以使用Element UI的lazy属性配合load方法实现按需加载。

async loadNode(node, resolve) {
if (node.level === 0) {
return resolve([{ id: 1, label: '根节点' }])
}
if (node.level >= 3) return resolve([])
const { data } = await api.getChildren(node.id)
resolve(data)
}






