侧边栏菜单的JS初始化

有小伙伴提到想用js初始化左侧菜单,这里简单写了个方法。

点击查看示例演示

注意:因IE浏览器不支持ES6的语法,请考虑自身的应用情况是否使用treeData方法(树状结构数据可由后端先处理完成,前端加载菜单时放在index.min.js之前)。

这里以iframe版本为例。您可以将下面的代码放到index.min.js中,要放到 ;jQuery( function() {}); 外面,然后直接使用 setSidebar(menus);,调用时传入的参数,可以是json字符串,也可以是对象,不需要是树状结构的。


/**
 * 菜单
 * @param data 菜单JSON数据
 *        id 菜单唯一ID
 *        name 菜单名称
 *        url 菜单链接地址
 *        icon 图标
 *        pid  父级ID
 *        is_out 是否外链0否|1是,外链a标签没有class='multitabs'
 *        is_home 是否首页
 */
var setSidebar = function(data){
    if (data.length == 0) return false;
    var treeObj = treeData(data, 'id', 'pid', 'children');
    html = createMenu(treeObj, true);
    $('.sidebar-main').append(html);
}

var createMenu = function (data, is_frist) {
    var menu_body = is_frist ? '<ul class="nav nav-drawer">' : '<ul class="nav nav-subnav">';
    
    for(var i = 0; i < data.length; i++){
        iframe_class = data[i].is_out == 1 ? '' : 'class="multitabs"';
        icon_div     = data[i].pid == 0 ? '<i class="' + data[i].icon + '"></i>' : '';
        selected     = (data[i].pid == 0) && (data[i].is_home == 1) ? 'active' : '';
        menuName     = data[i].pid == 0 ? '<span>' + data[i].name + '</span>' : data[i].name;
        if (data[i].children && data[i].children.length > 0) {
            menu_body += '<li class="nav-item nav-item-has-subnav"><a href="javascript:void(0)">' + icon_div + menuName + '</a>';
            menu_body += createMenu(data[i].children);
        } else {
            menu_body += '<li class="nav-item ' + selected + '"><a href="' + data[i].url + '" '+ iframe_class +'>' + icon_div + menuName + '</a>';
        }
        menu_body += '</li>';
    }
    
    menu_body += '</ul>';
    return menu_body;
};

/**
 * @author CSDN 蔚莱先森
 * @param source json数据源
 * @param id 主键ID
 * @param parendId 父级ID名称
 * @param children 子级名称
 */
var treeData = function (source, id, parentId, children){
    let cloneData = (typeof source == 'object') ? source : JSON.parse(source);
    return cloneData.filter(father=>{
        let branchArr = cloneData.filter(child => father[id] == child[parentId]);
        branchArr.length>0 ? father[children] = branchArr : ''
        return father[parentId] == 0
    })
}

菜单这一块的html代码,保留如下:


<div class="lyear-layout-sidebar-scroll">
  <nav class="sidebar-main"></nav>
</div>

也可以将代码封装到lightyear.js中,在index.html中引入,然后像这样调用 lightyear.sidebar(menus);


return {
    // 省略...
	
    // 左侧菜单
    sidebar : function(data) {
        setSidebar(data);
    }
};

记得最后return里面要加上上面的代码。最后附上一段菜单的json串。


  [{"id":"1","name":"后台首页","url":"lyear-main.html","pid":0,"icon":"mdi mdi-home","is_out":0,"is_home":1},{"id":"2","name":"UI 元素","url":"#","pid":0,"icon":"mdi mdi-palette","is_out":0,"is_home":0},{"id":"3","name":"按钮","url":"lyear_ui_buttons.html","pid":2,"icon":"","is_out":0,"is_home":0},{"id":"4","name":"卡片","url":"lyear_ui_cards.html","pid":2,"icon":"","is_out":0,"is_home":0},{"id":"5","name":"格栅","url":"lyear_ui_grid.html","pid":2,"icon":"","is_out":0,"is_home":0},{"id":"6","name":"多级菜单","url":"#","pid":0,"icon":"mdi mdi-menu","is_out":0,"is_home":0},{"id":"7","name":"一级菜单","url":"#!","pid":6,"icon":"","is_out":0,"is_home":0},{"id":"8","name":"一级菜单","url":"#!","pid":6,"icon":"","is_out":0,"is_home":0},{"id":"9","name":"二级菜单","url":"#!","pid":8,"icon":"","is_out":0,"is_home":0},{"id":"10","name":"二级菜单","url":"#!","pid":8,"icon":"","is_out":0},{"id":"11","name":"三级菜单","url":"#!","pid":10,"icon":"","is_out":0,"is_home":0},{"id":"12","name":"三级菜单","url":"#!","pid":10,"icon":"","is_out":0,"is_home":0}]

上面生成树状结构的方法不支持IE,附上另一个tree结构数据生成的方法


/**
 * 树状的算法
 * @params list     代转化数组
 * @params parentId 起始节点
 * @params idName 主键ID名
 * @params parentIdName 父级ID名称
 * @params childrenName 子级名称
 * @author CSDN博主「伤包子」
 */
function getTrees(list, parentId, idName, parentIdName, childrenName) {
    let items= {};
    // 获取每个节点的直属子节点,*记住是直属,不是所有子节点
    for (let i = 0; i < list.length; i++) {
         let key = list[i][parentIdName];
         if (items[key]) {
             items[key].push(list[i]);
         } else {
             items[key] = [];
             items[key].push(list[i]);
         }
     }
     return formatTree(items, parentId, idName, childrenName);
}

/**
 * 利用递归格式化每个节点
 */
function formatTree(items, parentId, idName, childrenName) {
    let result = [];
    if (!items[parentId]) {
        return result;
    }
    for (let t in items[parentId]) {
        items[parentId][t][childrenName] = formatTree(items, items[parentId][t][idName], idName, childrenName)
        result.push(items[parentId][t]);
    }
    return result;
}
2 条评论
  • Jason. Jason.
    2020-05-19 22:42:07

  • 我想对你说 我想对你说
    2020-01-10 16:01:30

    你好 菜单改成json格式渲染出来,然后渲染成顶部+左侧的三级菜单形式可以做个小案例吗