vue实现可选菜单树
Vue 实现可选菜单树
使用 Element UI 的 Tree 组件
Element UI 提供了 Tree 组件,支持复选框功能,可以直接用于实现可选菜单树。安装 Element UI 后,在 Vue 项目中引入 Tree 组件。
<template>
<el-tree
:data="menuData"
show-checkbox
node-key="id"
:default-expanded-keys="[2, 3]"
:default-checked-keys="[5]"
:props="defaultProps"
>
</el-tree>
</template>
<script>
export default {
data() {
return {
menuData: [
{
id: 1,
label: '一级菜单',
children: [
{
id: 2,
label: '二级菜单',
children: [
{ id: 3, label: '三级菜单' },
{ id: 4, label: '三级菜单' }
]
},
{
id: 5,
label: '二级菜单',
children: [
{ id: 6, label: '三级菜单' },
{ id: 7, label: '三级菜单' }
]
}
]
}
],
defaultProps: {
children: 'children',
label: 'label'
}
};
}
};
</script>
自定义递归组件实现菜单树
如果需要更灵活的控制,可以自定义递归组件实现菜单树。创建一个递归组件,支持复选框选择功能。
<template>
<div>
<tree-node
v-for="node in treeData"
:key="node.id"
:node="node"
@toggle-check="handleCheck"
/>
</div>
</template>
<script>
import TreeNode from './TreeNode.vue';
export default {
components: { TreeNode },
data() {
return {
treeData: [
{
id: 1,
label: '一级菜单',
checked: false,
children: [
{
id: 2,
label: '二级菜单',
checked: false,
children: [
{ id: 3, label: '三级菜单', checked: false },
{ id: 4, label: '三级菜单', checked: false }
]
}
]
}
]
};
},
methods: {
handleCheck(nodeId) {
const updateNode = (nodes) => {
nodes.forEach(node => {
if (node.id === nodeId) {
node.checked = !node.checked;
}
if (node.children) {
updateNode(node.children);
}
});
};
updateNode(this.treeData);
}
}
};
</script>
创建 TreeNode.vue 组件:
<template>
<div>
<div>
<input
type="checkbox"
:checked="node.checked"
@change="$emit('toggle-check', node.id)"
/>
{{ node.label }}
</div>
<div v-if="node.children" style="margin-left: 20px">
<tree-node
v-for="child in node.children"
:key="child.id"
:node="child"
@toggle-check="$emit('toggle-check', $event)"
/>
</div>
</div>
</template>
<script>
export default {
name: 'TreeNode',
props: {
node: {
type: Object,
required: true
}
}
};
</script>
使用第三方库 Vue-Tree-Select
Vue-Tree-Select 是一个专门用于树形选择菜单的库,支持单选、多选、搜索等功能。安装后可以直接使用。
npm install vue-tree-select
在 Vue 项目中使用:
<template>
<vue-tree-select
:options="treeOptions"
:value="selectedNodes"
@select="handleSelect"
multiple
/>
</template>
<script>
import VueTreeSelect from 'vue-tree-select';
export default {
components: { VueTreeSelect },
data() {
return {
treeOptions: [
{
id: 1,
label: '一级菜单',
children: [
{
id: 2,
label: '二级菜单',
children: [
{ id: 3, label: '三级菜单' },
{ id: 4, label: '三级菜单' }
]
}
]
}
],
selectedNodes: []
};
},
methods: {
handleSelect(selectedNodes) {
this.selectedNodes = selectedNodes;
}
}
};
</script>
父子节点联动选中
实现父子节点联动选中功能,可以在自定义递归组件中添加逻辑,选中父节点时自动选中所有子节点,或取消子节点时检查父节点状态。
methods: {
handleCheck(nodeId) {
const updateNode = (nodes) => {
nodes.forEach(node => {
if (node.id === nodeId) {
node.checked = !node.checked;
if (node.children) {
this.toggleChildren(node.children, node.checked);
}
}
if (node.children) {
updateNode(node.children);
}
});
};
updateNode(this.treeData);
},
toggleChildren(children, checked) {
children.forEach(child => {
child.checked = checked;
if (child.children) {
this.toggleChildren(child.children, checked);
}
});
}
}
获取选中节点数据
通过遍历树数据,收集所有选中节点的 ID 或完整数据,用于提交或进一步处理。
methods: {
getCheckedNodes() {
const checkedNodes = [];
const traverse = (nodes) => {
nodes.forEach(node => {
if (node.checked) {
checkedNodes.push(node);
}
if (node.children) {
traverse(node.children);
}
});
};
traverse(this.treeData);
return checkedNodes;
}
}
动态加载节点数据
对于大型菜单树,可以动态加载子节点数据以减少初始加载时间。在节点展开时加载子节点数据。
methods: {
loadNode(node, resolve) {
if (node.level === 0) {
resolve([{ id: 1, label: '一级菜单' }]);
} else {
setTimeout(() => {
resolve([
{ id: 2, label: '二级菜单' },
{ id: 3, label: '二级菜单' }
]);
}, 500);
}
}
}
在 Element UI 的 Tree 组件中使用:
<el-tree
:props="props"
:load="loadNode"
lazy
show-checkbox
>
</el-tree>
通过以上方法,可以实现灵活且功能丰富的可选菜单树,满足不同场景的需求。







