这次在原先html自定义垂直导航菜单的基础上做了比较大的改动:
1、去掉了font-awesome图标,上级菜单右边的箭头是自己用css写的,具体参考《css三角箭头》。
2、去掉了初始化时候打开的菜单的属性openIndex(考虑到多级菜单子菜单的打开方式,暂时去掉),添加了superLevel(默认是0,即当前添加的不论是一个JSArray还是JSObject,我们都将作为一级菜单(0+1)处理。)
3、将二级导航变为多级导航菜单,可以无限添加子菜单,你只需要在treeMenu.css的合适的地方添加或者修改自己的每个级别的css样式即可,这里我默认处理了三级菜单的样式。
3、在TreeMenu中添加圆角边框,添加鼠标滑过后的菜单Hover样式。
看下效果图(个人觉得比较素雅,完全有自己的元素在里面,修改起来很方便):
用到的css:
treeMenu.css
用到的js:
jquery-1.9.1.js
json2.js
checkutil.js(自己随手写的一个检测js对象类型的工具)
treeMenu.js(※※※※※这个才是重点 - -)
上代码(源码地址:http://files.cnblogs.com/files/wrcold520/TreeMenu.zip,html、css、js中的注释很详尽,如果有不对的地方,欢迎留言,3Q!!!):
html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="css/treeMenu.css" /> <script type="text/javascript" src="js/json2.js"></script> <script type="text/javascript" src="js/jquery-1.9.1.js"></script> <script type="text/javascript" src="js/checkutil.js"></script> <script type="text/javascript" src="js/treeMenu.js"></script> <title></title> </head> <style> body { background: lightgray; } .TreeMenuList>div { margin: 5px; } .TreeMenuList { /**flexbox兼容**/ display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ display: -moz-box; /* OLD - Firefox 19- (doesn't work very well) */ display: -ms-flexbox; /* TWEENER - IE 10 */ display: -webkit-flex; /* NEW - Chrome */ display: flex; /**flexbox兼容**/ -webkit-box-orient: horizontal; -webkit-flex-direction: row; -moz-flex-direction: row; -ms-flex-direction: row; -o-flex-direction: row; flex-direction: row; } </style> <body> <div class="TreeMenuList"> <div id="TreeMenu01"></div> <div id="TreeMenu02"></div> </div> <div class="TreeMenuList"> <div id="TreeMenu03"></div> <div id="TreeMenu04"></div> </div> </body> <script> var menus01 = [{ name: "menu1", href: "", subMenus: [{ name: "menu1.1", href: "", subMenus: [{ name: "menu1.1.1", href: "#menu1.1.1", }, { name: "menu1.1.2", href: "#menu1.1.2" }] }, { name: "menu1.2", href: "#menu1.2", subMenus: [{ name: "menu1.2.1", href: "#menu1.2.1" }, { name: "menu1.2.2", href: "#menu1.2.2" }] }, { name: "menu1.3", href: "#menu1.3", subMenus: [{ name: "menu1.3.1", href: "#menu1.3.1" }, { name: "menu1.3.2", href: "#menu1.3.2" }] }] }, { name: "menu2", href: "", subMenus: [{ name: "menu2.1", href: "", subMenus: [{ name: "menu2.1.1", href: "#menu2.1.1" }, { name: "menu2.1.2", href: "#menu2.1.2" }] }, { name: "menu2.2", href: "#", subMenus: [{ name: "menu2.2.1", href: "#menu2.2.1" }, { name: "menu2.2.2", href: "#menu2.2.2" }] }, { name: "menu2.3", href: "#menu2.3", subMenus: [{ name: "menu2.3.1", href: "#menu2.3.1" }, { name: "menu2.3.2", href: "#menu2.3.2" }] }] }, { name: "menu3", href: "", subMenus: [{ name: "menu3.1", href: "", subMenus: [{ name: "menu3.1.1", href: "#menu3.1.1" }, { name: "menu3.1.2", href: "#menu3.1.2" }] }, { name: "menu3.2", href: "#", subMenus: [{ name: "menu3.2.1", href: "#menu3.2.1" }, { name: "menu3.2.2", href: "#menu3.2.2" }] }, { name: "menu3.3", href: "#menu3.3", subMenus: [{ name: "menu3.3.1", href: "#menu3.3.1" }, { name: "menu3.3.2", href: "#menu3.3.2" }] }] }];
var menus02 = JSON.stringify(menus01); var menus03 = { name: "menu1", href: "", subMenus: [{ name: "menu1.1", href: "", subMenus: [{ name: "menu1.1.1", href: "#menu1.1.1", }, { name: "menu1.1.2", href: "#menu1.1.2" }] }, { name: "menu1.2", href: "#menu1.2", subMenus: [{ name: "menu1.2.1", href: "#menu1.2.1" }, { name: "menu1.2.2", href: "#menu1.2.2" }] }, { name: "menu1.3", href: "#menu1.3", subMenus: [{ name: "menu1.3.1", href: "#menu1.3.1" }, { name: "menu1.3.2", href: "#menu1.3.2" }] }] };
var menus04 = JSON.stringify(menus03);
var config01 = { treeMenuId: "#TreeMenu01", superLevel: 0, multiple: true, }; var config02 = { treeMenuId: "#TreeMenu02", superLevel: 0, multiple: false }; var config03 = { treeMenuId: "#TreeMenu03", superLevel: 0, multiple: true } var config04 = { treeMenuId: "#TreeMenu04", superLevel: 0, multiple: false } treeMenu.init(menus01, config01); treeMenu.init(menus02, config02); treeMenu.init(menus03, config03); treeMenu.init(menus04, config04); </script> </html>
treeMenu.css:
.TreeMenu { /** TreeMenu整体样式 **/ font-family: "edwardian script itc"; min-width: 300px; } .TreeMenu> .MenuBox { /** 不能选择文本 **/ cursor: pointer; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; -o-user-select: none; user-select: none; } .TreeMenu> .Radius { /** 圆角边框,添加圆角半径的上下Padding **/ background: white; border: 1px solid darkgray; border-radius: 8px; -webkit-border-radius: 8px; -moz-border-radius: 8px; padding-top: 8px; padding-bottom: 8px; } .TreeMenu ul, .TreeMenu ol { /** 去掉TreeMenu下面ul/ol的默认样式 **/ list-style: none; margin: 0; padding: 0; } .TreeMenu .MenuName { /** 所有菜单名称的样式 ,flex布局,垂直居中,两端对齐**/ align-items: center; /**flexbox兼容**/ display: flex; display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ display: -moz-box; /* OLD - Firefox 19- (doesn't work very well) */ display: -ms-flexbox; /* TWEENER - IE 10 */ display: -webkit-flex; /* NEW - Chrome */ /**flexbox兼容**/ flex-direction: row; -webkit-box-orient: horizontal; -webkit-flex-direction: row; -moz-flex-direction: row; -ms-flex-direction: row; -o-flex-direction: row; justify-content: space-between; -webkit-justify-content: space-between; } .TreeMenu .Level-1 .MenuName { /** 一级菜单菜单名称样式 **/ color: mediumpurple; font-size: 20px; padding: 8px 10px 8px 10px; } .TreeMenu .Level-2 .MenuName { /** 二级菜单菜单名称样式 **/ color: darkred; font-size: 18px; padding: 8px 10px 8px 20px; } .TreeMenu .Level-3 .MenuName { /** 三级菜单菜单名称样式 **/ color: darkslategrey; font-size: 16px; padding: 8px 10px 8px 30px; } .TreeMenu .MenuName:hover { /** 鼠标滑过菜单样式 **/ background: #E3E3E3; font-weight: 600; } .TreeMenu .Level-1 { /** 一级菜单li **/ border-bottom: 1px solid gainsboro; } .TreeMenu .Level-1:last-child { /** 最后一个一级菜单左下、右下圆角 **/ border-bottom: 0px; } .TreeMenu .Level-2 { /** 二级菜单li **/ border-top: 1px solid gainsboro; margin: 0px 10px; } .TreeMenu .Level-3 { /** 三级菜单li **/ border-top: 1px solid gainsboro; margin: 0px 20px; } .TreeMenu .TreeArrowDown { /** 右边三角箭头的样式 **/ border-left: 6px solid transparent; border-right: 6px solid transparent; border-top: 10px solid darkgray; display: inline-block; width: 0px; height: 0px; transition: all 0.5s ease; -webkit-transition: all 0.5s ease; -moz-transition: all 0.5s ease; -ms-transition: all 0.5s ease; -o-transition: all 0.5s ease; } .TreeMenu .Level.active .TreeArrowDown.rotate { /** 选中当前菜单右边三角箭头逆时针旋转180度 **/ -webkit-transform: rotate(-180deg); -moz-transform: rotate(-180deg); -ms-transform: rotate(-180deg); -o-transform: rotate(-180deg); transform: rotate(-180deg); } .TreeMenu .Level .MenuBox { /** 默认不显示所有下级菜单 **/ display: none; } .TreeMenu a, .TreeMenu a:link, .TreeMenu a:hover, .TreeMenu a:active, .TreeMenu a:visited { /** 去掉a标签样式 **/ color: inherit; text-decoration: none; }
treeMenu.js:
/** * //1、menu01: JS Array * var menus01 = [{ * name: "menu1", * href: "", * subMenus: [{ * name: "menu1.1", * href: "", * subMenus: [{ * name: "menu1.1.1", * href: "#menu1.1.1", * }, { * name: "menu1.1.2", * href: "#menu1.1.2" * }] * }, * ....//省略若干子菜单 * ] * }, * ...//省略若干菜单 * ]; * * //2、menu02:JSON Array * var menus02 = JSON.stringify(menus01); * * //3、menu03: JS Object * var menus03 = { * name: "menu1", * href: "", * subMenus: [{ * name: "menu1.1", * href: "", * subMenus: [{ * name: "menu1.1.1", * href: "#menu1.1.1", * }, { * name: "menu1.1.2", * href: "#menu1.1.2" * }] * }, { * name: "menu1.2", * href: "#menu1.2", * subMenus: [{ * name: "menu1.2.1", * href: "#menu1.2.1" * }, { * name: "menu1.2.2", * href: "#menu1.2.2" * }] * }, { * name: "menu1.3", * href: "#menu1.3", * subMenus: [{ * name: "menu1.3.1", * href: "#menu1.3.1" * }, { * name: "menu1.3.2", * href: "#menu1.3.2" * }] * }] * }; * * //4、JSON object * var menus04 = JSON.stringify(menus03); * * var config01 = { * treeMenuId: "#TreeMenu01", //required * superLevel: 0, //optional * multiple: true, //optional * }; * * var config02 = { * treeMenuId: "#TreeMenu02", //required * superLevel: 0, //optional * multiple: false //optional * }; * * var config03 = { * treeMenuId: "#TreeMenu03", //required * superLevel: 0, //optional * multiple: true //optional * } * * var config04 = { * treeMenuId: "#TreeMenu04", //required * superLevel: 0, //optional * multiple: false //optional * } * treeMenu.init(menus01, config01); * treeMenu.init(menus02, config02); * treeMenu.init(menus03, config03); * treeMenu.init(menus04, config04); * * @author DarkRanger * see more https://coding.net/u/wrcold520/p/TreeMenu-Simple-Tree-Menu-js/git/tree/master/TreeMenu * */ ! function($, JSON, checkutil) { "use strict"; var treeMenu = {}; treeMenu.name = "MenuTree-Simple Left Navigation Tree Menu"; treeMenu.version = "version-1.0"; treeMenu.author = "DarkRanger"; treeMenu.email = "15934179313@163.com"; treeMenu.url = "https://coding.net/u/wrcold520/p/TreeMenu-Simple-Tree-Menu-js/git/tree/master/TreeMenu"; treeMenu.config = function() {}; treeMenu.init = function(datas, config) { var menuConfig = new treeMenu.config(); if(checkutil.isUndefined(datas)) { console.log("The function treeMenu.init() doesn't have the parameter 'datas' that means the treeMenu has no Datas!"); return; } else { //JS Object or JS Array if(checkutil.isArray(datas)) { menuConfig.menus = datas; } else if(checkutil.isObject(datas)) { menuConfig.menus = [datas]; } //JSONString else if(checkutil.isString(datas)) { var menuObj; try { var menuJson = JSON.parse(datas); if(checkutil.isArray(menuJson)) { menuObj = menuJson; } else if(checkutil.isObject(menuJson)) { menuObj = [menuJson]; } menuConfig.menus = menuObj; } catch(e) { throw new Error(e); } } if(checkutil.isUndefined(menuConfig.menus)) { console.warn("datas is not jsonString or JS Object or JS Array, configure failed!!!"); return; } } if(checkutil.isUndefined(config)) { console.log("The function treeMenu.init() doesn't have the parameter 'config' that means the treeMenu has no event!"); } else { if(checkutil.isUndefined(config.treeMenuId)) { console.warn("Your TreeMenu config has not key['treeMenuId'], configure failed!!!\nPlease configure your unique treeMenu by treeMenuId!"); return; } else if($(config.treeMenuId).length == 0) { console.warn("Cannot find your treeMenu[id: " + config.treeMenuId + "], configure failed!!! "); return; } else { menuConfig.treeMenuId = config.treeMenuId; } if(checkutil.isUndefined(config.superLevel)) { console.warn("Your config has not key['superLevel'], default value is 0 that means you your datalist'superlevel is 0!"); menuConfig.superLevel = 0; } else if(!checkutil.isNumber(config.superLevel)) { console.warn("Your config's parameter['superLevel'] shoule be a Number, configure failed!"); return; } else { menuConfig.superLevel = config.superLevel; } if(checkutil.isUndefined(config.multiple)) { console.warn("Your config has not key['multiple'], default value is false that means you could open one spMenu at most at the same time!"); menuConfig.multiple = false; } else { menuConfig.multiple = config.multiple; } menuConfig.multiple = config.multiple; } genDomTree(menuConfig); initEvent(menuConfig); } /** * 生成dom树 * @param {Object} menuConfig */ function genDomTree(menuConfig) { var $treeMenu = $(menuConfig.treeMenuId); var menus = menuConfig.menus; var multiple = menuConfig.multiple; var hasTreeMenuClass = $treeMenu.hasClass("TreeMenu"); if(hasTreeMenuClass === false) { $treeMenu.addClass("TreeMenu"); } var firstLevel = menuConfig.superLevel; eachMenusDom($treeMenu, menus, firstLevel); } /** * 递归生成dom树 * @param {Object} superEle 在哪个元素下添加子元素 * @param {Object} subMenus 子元素的集合 JS Array * @param {Object} superLevel 上级元素的等级 */ function eachMenusDom(superEle, subMenus, superLevel) { var level = superLevel + 1; var ulBox01 = $("<ul>", { "class": "MenuBox MenuBox-" + level+" Radius", }); $.each(subMenus, function(i, menu) { var liItem = $("<li>", { "class": "Level Level-" + level, }); var menuNameDiv = $("<div>", { "class": "MenuName", }); var menuLink = $("<a>"); var hasHref = menu.href && $.trim(menu.href).length > 0; if(hasHref === true) { menuLink.attr("href", menu.href); } var hasName = menu.name && menu.name.length > 0; if(hasName === true) { menuLink.text(menu.name); } menuLink.appendTo(menuNameDiv); menuNameDiv.appendTo(liItem); liItem.appendTo(ulBox01); ulBox01.appendTo(superEle); var subMenus = menu.subMenus; if(subMenus && checkutil.isArray(subMenus) && subMenus.length > 0) { var arrowDownDiv = $("<div>", { "class": "TreeArrowDown" }); arrowDownDiv.appendTo(menuNameDiv); eachMenusDom(liItem, subMenus, level); } }); } /** * 初始化点击事件 * @param {Object} menuConfig */ function initEvent(menuConfig) { $(menuConfig.treeMenuId + " .MenuName").on("click", function() { var $arrow = $(this).find(".TreeArrowDown"); var $menuBox = $(this).next(); var $menuItem = $(this).parent(); $menuBox.slideToggle(); $arrow.toggleClass("rotate"); $menuItem.toggleClass("active"); if(menuConfig.multiple === false) { var $brothers = $menuItem.siblings(); $brothers.find(".MenuBox").slideUp(); $brothers.find(".TreeArrowDown").removeClass("rotate"); $brothers.removeClass("active"); } }); } window.treeMenu = treeMenu; }($, JSON, checkutil);
附上源码:TreeMenu.zip