级联选择器根据最后一级id找到完整的路径
1、解决方案
function findPathByMenuId(menuId) {
let path = []
let queue = [{ node: modelList.value, path: [] }]
// 使用 while 循环处理队列,直到找到目标或队列为空
while (queue.length > 0) {
const { node, path: currentPath } = queue.shift()
for (const item of node) {
if (item.id === menuId.toString()) {
// 找到目标,返回完整路径
return currentPath.concat(item.id)
}
if (Array.isArray(item.subNodes)) {
// 将子节点及其路径加入队列
queue.push({ node: item.subNodes, path: currentPath.concat(item.id) })
}
}
}
// 未找到目标,返回空路径
return path
}
代码解析:
- 初始化:
path:初始化一个空数组,用于存储从根节点到目标节点的路径。
queue:初始化一个队列,用于广度优先搜索。队列的第一个元素是一个对象,包含:
node:初始为 modelList.value,即整个菜单树的根节点。
path:初始为空数组,表示还没有经过任何节点。
- 广度优先搜索:
使用 while 循环,只要队列不为空,就持续进行搜索。
queue.shift() 从队列头部取出一个元素,这保证了先进先出的原则,符合广度优先搜索的要求。
解构取出 node 和 currentPath,分别表示当前处理的节点集合和到达这些节点的路径。
- 节点处理:
遍历 node 中的每一个 item:
匹配检查:如果 item.id 与 menuId 匹配,说明找到了目标节点,将 item.id 追加到 currentPath 并返回这个路径。
子节点处理:如果 item 有子节点(item.subNodes 是一个数组),创建一个新的队列元素,将子节点和当前路径追加 item.id 后的结果放入队列的末尾,等待后续处理。
- 返回结果
如果遍历完所有队列元素仍未找到目标节点,返回初始的 path 变量,此时 path 应该还是空数组,表示没有找到目标节点。
2、示例
const modelList = [
{
id: "13",
menuName: "设施管理",
parentId: "0",
subNodes: [
{
id: "22",
menuName: "设备维修",
parentId: "13",
subNodes: [
{
id: "25",
menuName: "维修记录",
parentId: "22",
subNodes: []
}
]
}
]
},
{
id: "92",
menuName: "安全管理",
parentId: "0",
subNodes: [
{
id: "93",
menuName: "安全准入",
parentId: "92",
subNodes: [
{
id: "99",
menuName: "项目准入",
parentId: "93",,
subNodes: [
{
id: "100",
menuName: "项目审核",
parentId: "99",
subNodes: []
}
]
}
]
}
]
}
];
如果最后一级的id是100
那path就是[‘92’, ‘93’, ‘99’, ‘100’]
然后直接把path赋值给menuId即可正常回显!
<el-form-item label="所属模块:" prop="menuId">
<el-cascader v-model="form.menuId" :options="modelList" :props="defaultProps" placeholder="请选择" style="width: 625px" @change="handleChangeModule" />
</el-form-item>