js菜单树子节点展示菜单完整路径信息

需求场景:在树形菜单中,仅子节点展示当前菜单完整路径信息(即拼接所有的父级菜单和自身),根节点和叶子节点不展示。子节点,在树结构中,除了根节点和叶子节点外的所有节点。

图文描述:

如图中,在不涉及 子节点展示菜单完整路径信息时,菜单树每个选择项都是单个描述,如顶级菜单根节点名称Parent, 子节点名称Child, 叶子节点Grand Child。为明晰展示菜单所处位置,虽然这样展示已经够明晰了,但总有些ui有些奇怪的想法,需要在子节点上展示父节点信息,来体现层次。为此,就有了红色字体标注部分。

定义已知的条件:

每一个节点都对应一条菜单信息数据,字段信息为:

{id: xxx, menuName: xxx, children: [], pmenuId: xxx, pmenuName: xxx,label: xxx}, 其中label字段是el-tree组件展示时所采用的key,该字段值默认与menuName一致,对于子节点时,需要重新设置值。

菜单树数据集>>

treeMenuList,如使用elementui前端框架中的el-tree组件来实现,该treeMenuList就是该组件需要的数据结构。

数据库查询出的菜单信息列表>>

arrAllMenu,包含了菜单树所有节点所涉及的菜单信息,只不过该列表是已经去树形结构了,简单便于遍历与补植。当然,也可以将treeMenuList递归平衡化得到一份儿简单的列表数据。

处理思路:

普遍思路采用递归,然后按顺序组装数据。

1、递归遍历菜单树数据集treeMenuList,获取里面涉及到的子节点集合arrChildNode。

2、forEach循环遍历arrChildNode,递归获取每一个子节点的全部父节点,并拼接父节点菜单信息。

3、递归遍历菜单树数据集treeMenuList,结合步骤2填充了父节点层次信息的子节点集合,重新设置子节点的label值。

相关代码:

// 处理子节点显示父级菜单名称追加相关方法  ==========================begin==================
// 子节点:在树结构中,除了根节点和叶子节点外的所有节点。
// 每个节点均是一个菜单信息 {id: xxx, menuName: xxx, children: [], pmenuId: xxx, pmenuName: xxx}
/**
 * 获取指定父节点的子节点.
 * @param parentNode 父节点
 * @param arrChildNode 子节点列表
 */
export function getAllChildNode(parentNode, arrChildNode) {
    if (parentNode.children && parentNode.children.length > 0) {
        //有下级,是一个数组
        let children = parentNode.children;
        children.forEach(node => {
            if (node.children && node.children.length > 0) {
                //此时node有下级,因此node是子节点
                arrChildNode.push(node);
                //当前节点作为父节点, 递归遍历
                getAllChildNode(node, arrChildNode);
            }
        });
    }
}

/**
 * 获取指定子节点的所有父节点.(深度由大到小)
 * @param childNode 子节点
 * @param arrParentNode 父节点列表
 * @param arrAllMenu 所有菜单信息列表
 */
export function getAllParentNode(childNode, arrParentNode, arrAllMenu) {
    let pId = childNode.pmenuId;
    
    let parentNode = arrAllMenu.find(menu => {
        return menu.id === pId;
    });
    if (parentNode) {
        arrParentNode.push(parentNode);
        if (parentNode.pmenuId) {
            //如果还存在父级,就将当前父级作为子级,递归遍历
            getAllParentNode(parentNode, arrParentNode, arrAllMenu);
        }
    }
}

/**
 * 获取树形菜单列表中子节点标签填充了父级信息后的子节点列表.
 * @param treeMenuList 树形菜单列表
 * @param arrAllMenu 所有菜单信息列表
 */
export function getFilledChildNodeLabelAboutParentInfo(treeMenuList, arrAllMenu) {
    //菜单树中的子节点列表
    let arrChildNode = [];
    if (treeMenuList && treeMenuList.length > 0) {
        //遍历一级菜单,均视为父节点
        treeMenuList.forEach(item => {
            getAllChildNode(item, arrChildNode);
        });

        console.log('菜单树列表中的子节点信息:', arrChildNode);
        if (arrChildNode.length > 0) {
            arrChildNode.forEach(childItem => {
                //当前子节点的所有父节点列表,深度由大到小
                let arrCurrentParentNode = []; 
                getAllParentNode(childItem, arrCurrentParentNode, arrAllMenu);
                //倒序一下,深度由小到大
                arrCurrentParentNode.reverse();
                let itemLable = '';
                //拼接父级菜单名
                arrCurrentParentNode.forEach(item => {
                    itemLable = itemLable + item.menuName + '/';
                });
                //拼接自己
                itemLable = itemLable + childItem.menuName;
                //重新设置el-tree中的显示标签信息
                childItem.label = itemLable;
            });
        }
        console.log('菜单树列表中的子节点填充父级信息后:', arrChildNode);
    }
    return arrChildNode;
}

/**
 * 填充树形菜单列表中子节点标签关于父级信息.
 * @param treeMenuList 树形菜单列表
 * @param arrChildNode 填充了父级信息的子节点平衡列表
 */
export function fillTreeMenuChildNodeLabelAboutParentInfo(treeMenuList, arrChildNode) {
    //获取填充了父级信息的子节点平衡列表
    if (arrChildNode.length > 0) {
        //遍历
        treeMenuList.forEach(item => {
            let itemId = item.id;
            let needFillItem = arrChildNode.find(node => {
                return node.id === itemId;
            });
            if (needFillItem) {
                //存在,则设置值
                item.label = needFillItem.label;
            }
            if (item.children && item.children.length > 0) {
                //当前子级作为treeList继续遍历
                fillTreeMenuChildNodeLabelAboutParentInfo(item.children, arrChildNode);
            }
        });
    }
}

/**
 * 填充菜单树中标签父级信息入口方法.
 * @param treeMenuList 树形菜单列表
 * @param arrAllMenu 所有菜单信息列表
 */
export function fillTreeMenuLabelAboutParentInfoMain(treeMenuList, arrAllMenu) {
    let arrChildNode = getFilledChildNodeLabelAboutParentInfo(treeMenuList, arrAllMenu);
    fillTreeMenuChildNodeLabelAboutParentInfo(treeMenuList, arrChildNode);
}

// 处理子节点显示父级菜单名称追加相关方法  ==========================end==================

页面调用处理是,只需要调用fillTreeMenuLabelAboutParentInfoMain即可。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值