SOURCE

console 命令行工具 X clear

                    
>
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;
}