console
class Menu {
constructor(place,template) {
this.place = place;
this.template = template;
this.init();
}
init() {
this.menuOuter = document.createElement('div');
this.menuOuter.classList.add('menu-outer','clear');
this.place.appendChild(this.menuOuter);
this.templateToElement();
}
templateToElement() {
let that = this;
let n = 0;
function addListener(obj,listeners) {
if(!obj) {
return;
}
for(let key in listeners) {
let type = listeners[key];
for(let k in type) {
obj.addEventListener(key,type[k]);
}
}
}
function deepTraversal(obj,parent) {
for(let key in obj) {
let item = obj[key];
let el = null;
if(n == 0) {
el = elt('div',"",["menu-item-inline"]);
el.appendChild(elt('span',item.label))
parent.appendChild(el);
} else {
el = elt('div',item.label,['menu-item']);
parent.appendChild(el);
}
addListener(el,item.listeners);
if(item.sub) {
let newparent = null;
if(n==0) {
newparent = elt('div',"",["item-list","below"]);
} else {
newparent = elt('div',"",["item-list","left"])
}
if(el) {
el.appendChild(newparent);
}
n++;
deepTraversal(item.sub,newparent);
n--;
}
}
}
function elt(tagName,textContent="",classname,style={}) {
let el = document.createElement(tagName);
el.textContent = textContent;
if(typeof classname == 'string' && classname.trim() != "") {
el.classList.add(classname);
} else if (classname instanceof Array) {
classname.forEach(function(item){
el.classList.add(item);
});
}
Object.assign(el.style,style);
return el;
}
deepTraversal(this.template,this.menuOuter);
let w = 0;
Array.from(this.menuOuter.children).forEach(item=>{
w += parseInt(getComputedStyle(item).width);
});
this.menuOuter.style.width = `${w}px`;
}
}
let place = document.querySelector("#root");
let template = [
{
label: "文件",
sub: [
{
label: "打开",
listeners: {
"click": [
function () {
console.log("打开")
},
]
}
},
{
label: "新建",
},
{
label: "关闭",
sub: [
{
label: "关闭项目"
},
{
label: "关闭文件",
sub: [
{
label: "关闭并保存"
},
{
label: "直接关闭",
sub: [
{
label: "item1"
},
{
label: 'item2'
}
]
}
]
}
]
}
]
},
{
label: "编辑"
},
{
label: "运行"
},
{
label: "帮助",
sub: [
{
label: "打开开发者工具"
}
]
}
]
let menu = new Menu(place,template);
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=, initial-scale=">
<meta http-equiv="X-UA-Compatible" content="">
<title></title>
</head>
<body>
<div id="root"></div>
</body>
</html>
* {
margin: 0;
padding: 0;
}
.menu-outer {
position: absolute;
left: 0;
top: 0;
background: #23272e;
color: #eee;
cursor: pointer;
user-select: none;
font-size: 14px;
height: 30px;
}
.clear::after {
content: "";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.menu-item-inline {
position: relative;
float: left;
height: 30px;
line-height: 30px;
}
.menu-item-inline>span {
display: block;
height: 100%;
padding: 0 20px;
}
.menu-item {
position: relative;
cursor: pointer;
user-select: none;
color: #eee;
background: inherit;
font-size: 12px;
text-align: left;
padding-right: 10px;
padding-left: 2em;
line-height: 25px;
white-space: nowrap;
}
.menu-item:hover {
background: #35393d;
}
.item-list {
background: #23272e;
display: none;
min-width: 100px;
}
.left {
position: absolute;
left: calc(100% + -1px);
top: 0;
}
.below {
position: absolute;
left: 0;
top: calc(100% + 0px);
}
.menu-outer *:not(.item-list):hover {
background: #35393d;
}
.menu-item:hover>.item-list {
display: block;
}
.menu-item-inline:hover>.item-list {
display: block;
}