JS实现左侧菜单工具栏

Kamiisa ·
更新时间:2024-11-01
· 1261 次阅读

本文实例为大家分享了JS实现左侧菜单工具栏的具体代码,供大家参考,具体内容如下

摘要

该js脚本可帮助你快速实现左侧菜单工具栏。通过js封装成一个方法类,直接new该对象即可快速生成左侧菜单工具栏。

一、效果展示 

二、menu.js文件 

(1)WenMenuNode节点

let WenMenuNode = function ({                                 text,                                 wenMenu,                                 attributes = {},                                 subs = [],                                 parentElement = null,                                 iconHTML = '',                                 level = 1,                                 parentNode = null,                                 isActive = false,                                 onLaunch = null,                             }) {     this._level = level;     this._text = text;     this._attributes = attributes;     this._wenMenu = wenMenu;     this._subs = subs;     this._onLaunch = onLaunch;     this._childHeight = 0;     this._height = 0;     this.style = {         childHeight: 0,     }     this._parentElement = parentElement;     this._parentNode = parentNode;     this._element = this._wenMenu.createElement('li', {         class: "wen-menu-li",     });     this._textElement = this._wenMenu.createElement('a', this._attributes);     this._iconHTML = iconHTML;     this._childNodes = [];     this._childElement = null;     this._activeChild = null;     if (this._parentElement) this._parentElement.append(this._element);     this._isActive = isActive;     if (this._isActive) {         if (this._level == 1) {             this._wenMenu._activeMenu = this;         } else if (this._parentNode) {             this._parentNode._activeChild = this;         }     }     this.create().onLaunch(); } WenMenuNode.prototype.create = function () {     let a = this._textElement;     let icon = this._wenMenu.createElement('i', {         class: "wen-menu-icon",     })     if (this._level > 1) {         a.innerHTML = '<span class="wen-menu-tree">--</span>';     }     icon.innerHTML = this._iconHTML;     a.append(icon);     a.innerHTML += `<span class="wen-menu-text">${this._text}</span>`;     if (this._level == 1) {         a.classList.add('wen-menu-first');     }     this._element.append(a);     if (this._subs.length) {         let ul = this._wenMenu.createElement('ul', {             class: "wen-menu-ul" + (this._level == 1 ? " wen-menu-ul-second" : ""),         });         this._element.append(ul);         this._childElement = ul;         this._subs.forEach((item, i) => {             let node = new WenMenuNode({                 text: item.text,                 wenMenu: this._wenMenu,                 attributes: item.attributes,                 subs: item.subs,                 parentElement: ul,                 iconHTML: item.iconHTML,                 level: this._level + 1,                 parentNode: this,                 isActive: this._isActive && i == 0,                 onLaunch: (childNode) => {                     this._childNodes.push(childNode);                     if (i == this._subs.length - 1) {                         this.setEventListener(true);                     }                 }             });         });     } else {         this.setEventListener(false);     }     return this; } WenMenuNode.prototype.onLaunch = function () {     if (this._onLaunch) {         this._onLaunch.call(this._parentNode, this);     }     return this; } WenMenuNode.prototype.setEventListener = function (hasSub = false) {     if (hasSub) {         this._height = this._subs.length * this._wenMenu._menuHeight;         this._childHeight = this._childElement.clientHeight;         if (this._isActive) {             this._textElement.setAttribute('wen-active', '');             this._textElement.setAttribute('wen-expand', '');             this.style.childHeight = this._childHeight + this._wenMenu._menuSpacing;         } else {             this._textElement.setAttribute('wen-icon', '')             this._textElement.setAttribute('wen-collapse', '');             this.style.childHeight = 0;         }         this._childElement.style.height = this.style.childHeight + "px";         this._textElement.addEventListener('click', (e) => {             if (this._wenMenu._autoCollapse) {                 this.resetHeight();                 this.setHeight({                     menuNode: this,                 })             } else {                 let height = 0, target = e.target;                 if (target.classList.value.indexOf('wen-menu-text') >= 0) {                     target = target.parentElement;                 }                 if (target.getAttribute('wen-expand') === null) {                     // todo:: 展开                     height = this.style.childHeight = this._height + this._wenMenu._menuSpacing;                     target.setAttribute('wen-expand', '');                     target.removeAttribute('wen-collapse');                 } else {                     // todo:: 收起                     height = -this.style.childHeight;                     this.style.childHeight = 0;                     target.setAttribute('wen-collapse', '');                     target.removeAttribute('wen-expand');                     this.resetHeight(this._childNodes)                 }                 this._childElement.style.height = this.style.childHeight + 'px';                 if (this._parentNode) {                     this.setHeight({                         menuNode: this._parentNode,                         direction: 'up',                         childHeight: height,                         childNode: this,                     })                 }             }         });     } else {         if (this._isActive) {             this._textElement.classList.add('wen-active');         }         this._textElement.addEventListener('click', (e) => {             if (this._wenMenu._autoCollapse) {                 this.resetHeight();                 this.setHeight({                     menuNode: this._parentNode,                     direction: 'up',                     childNode: this,                     childHeight: this._height,                 })             }             this.removeActive(this._wenMenu._activeMenu)             this._isActive = true;             this._textElement.classList.add('wen-active');             let target = e.target;             if (target.classList.value.indexOf('wen-menu-text') >= 0) {                 target = target.parentElement;             }             if (target.classList.value.indexOf('wen-menu-first') >= 0) {                 this._wenMenu._activeMenu = this;             } else if (this._parentNode) {                 this.addActive(this._parentNode, this)             } else {                 this._wenMenu._activeMenu = this;             }             if (this._wenMenu._event) {                 this._wenMenu._event.call(this, e)             }         });     }     return this; } WenMenuNode.prototype.setHeight = function ({                                                 menuNode = null,                                                 direction = 'down',                                                 childHeight = 0,                                                 childNode = null,                                             }) {     if (!menuNode) {         return 0;     }     menuNode._textElement.setAttribute('wen-expand', '');     menuNode._textElement.removeAttribute('wen-collapse');     if (this._wenMenu._autoCollapse) {         menuNode.style.childHeight = menuNode._height;     }     if (direction == 'down') {         if (menuNode._subs.length) {             menuNode.style.childHeight += (this._wenMenu._menuSpacing * (childNode ? childNode._level : 1));             if (menuNode._isActive) {                 menuNode.style.childHeight += this.setHeight({                     menuNode: menuNode._activeChild,                 });             }             if (menuNode._childElement) {                 menuNode._childElement.style.height = menuNode.style.childHeight + "px";             }             if (menuNode._parentNode) {                 this.setHeight({                     menuNode: menuNode._parentNode,                     direction: 'up',                     childNode: menuNode,                     childHeight: menuNode.style.childHeight,                 });             }         }     } else {         menuNode.style.childHeight += (childHeight + this._wenMenu._menuSpacing);         menuNode._childElement.style.height = menuNode.style.childHeight + "px";         if (menuNode._parentNode) {             this.setHeight({                 menuNode: menuNode._parentNode,                 direction: 'up',                 childHeight: menuNode.style.childHeight,                 childNode: menuNode,             });         }     }     return menuNode.style.childHeight; } WenMenuNode.prototype.resetHeight = function (menuNodes) {     if (!menuNodes) {         menuNodes = this._wenMenu._menuNodes;     }     menuNodes.forEach((node) => {         if (node._childElement) {             node.style.childHeight = 0;             node._childElement.style.height = '0px';         }         if (node._childNodes.length) {             node._textElement.setAttribute('wen-collapse', '');             node._textElement.removeAttribute('wen-expand');             this.resetHeight(node._childNodes);         }     });     return this; } WenMenuNode.prototype.addActive = function (menuNode, activeChildNode) {     menuNode._isActive = true     menuNode._textElement.setAttribute('wen-active', '');     menuNode._textElement.removeAttribute('wen-icon');     if (this._wenMenu._autoCollapse) {         menuNode._textElement.setAttribute('wen-expand', '');         menuNode._textElement.removeAttribute('wen-collapse');     }     menuNode._activeChild = activeChildNode;     if (menuNode._parentNode) {         this.addActive(menuNode._parentNode, menuNode);     } else {         this._wenMenu._activeMenu = menuNode;     }     return this; } /**  * 去除active属性  * @param    WenMenuNode menuNode  * @return    WenMenuNode  */ WenMenuNode.prototype.removeActive = function (menuNode) {     menuNode._isActive = false;     if (menuNode._subs.length) {         menuNode._textElement.removeAttribute('wen-active');         menuNode._textElement.setAttribute('wen-icon', '');         if (this._wenMenu._autoCollapse) {             menuNode._textElement.setAttribute('wen-collapse', '');             menuNode._textElement.removeAttribute('wen-expand');         }         if (menuNode._activeChild) {             this.removeActive(menuNode._activeChild);         }     } else {         menuNode._textElement.classList.remove('wen-active');     }     return this; }

(2) WenMenu对象 

let WenMenu = function ({                             ele,                             menus,                             event = null,                             attributes = {},                             menuHeight = 35,                             menuSpacing = 0,                             autoCollapse = true,                             duration = 300,                         }) {     this._ele = ele;     this._duration = duration;     this._menus = menus;     this._event = event;     this._menuNodes = [];     this._autoCollapse = autoCollapse;     this.style = {         width: '100%',         height: '100%',     }     this._menuElement = this.createElement('ul', attributes);     this._menuElement.classList.value += 'wen-menu-ul wen-menu-ul-first';     this._ele.append(this._menuElement);     this._activeMenu = null;     this._menuHeight = menuHeight;     this._menuSpacing = menuSpacing;     this.init().createStyle().createMenu(); }; WenMenu.prototype.init = function () {     if (this._ele.clientHeight) {         this._ele.style.overflow = 'hidden';         this._menuElement.style['overflow-y'] = 'scroll';         let scrollWidth = this._menuElement.offsetWidth - this._menuElement.clientWidth;         this.style.width = 'calc(100% + ' + scrollWidth + 'px)';         this.style.height = this._ele.clientHeight + 'px';     }     return this; } /**  * 创建菜单  */ WenMenu.prototype.createMenu = function () {     this._menus.forEach((item, i) => {         let node = new WenMenuNode({             text: item.text,             attributes: item.attributes,             subs: item.subs,             parentElement: this._menuElement,             wenMenu: this,             isActive: i == 0,         });         this._menuNodes.push(node);     });     return this; }; /**  * 创建元素  * @param    tagName  * @param    attributes  * @returns    {HTMLElement}  */ WenMenu.prototype.createElement = function (tagName, attributes = {}) {     let ele = document.createElement(tagName);     function checkValue(value) {         if (Object.prototype.toString.call(value) === "[object Array]") {             value = value.join(',');         } else if (Object.prototype.toString.call(value) === '[object Object]') {             var valueStr = '';             Object.keys(value).forEach(function (name) {                 valueStr += name + ":" + checkValue(value[name]) + ";";             });             value = valueStr;         }         return value;     }     if (attributes) {         Object.keys(attributes).forEach((name) => {             let value = checkValue(attributes[name]);             ele.setAttribute(name, value);         })     }     return ele; }; WenMenu.prototype.createStyle = function () {     let style = this.createElement('style'),         head = document.querySelector('head');     style.innerHTML = `         .wen-menu-ul-first, .wen-menu-ul-first *{             padding: 0px;             margin: 0px;             border-spacing: 0px;             list-style: none;         }         .wen-menu-ul-first{             width: ${this.style.width};             height: ${this.style.height};         }         .wen-menu-ul {             overflow: hidden;         }         .wen-menu-ul-first, .wen-menu-ul-second {             background: rgba(0, 0, 0, 0.1);         }         .wen-menu-li {             padding-left: 22px;             -webkit-box-sizing: border-box;             -moz-box-sizing: border-box;             box-sizing: border-box;         }         .wen-menu-ul-first > .wen-menu-li {             padding: 0px;         }         .wen-menu-ul-second > .wen-menu-li {             padding: 0px 0px 0px 18px;         }         .wen-menu-tree {             border-left: 1px dashed rgba(0, 0, 0, 1);             width: 16px;         }         .wen-menu-text{             width: calc(100% - 16px);             display: flex;             overflow: hidden;             white-space: nowrap;             text-overflow: ellipsis;             -o-text-overflow: ellipsis;         }         .wen-menu-li a {             display: inline-block;             width: 100%;             height: ${this._menuHeight}px;             -webkit-box-sizing: border-box;             -moz-box-sizing: border-box;             box-sizing: border-box;             position: relative;             cursor: pointer;             display: flex;             align-items: center;         }         .wen-menu-ul, .wen-menu-li a[wen-icon]:after, .wen-menu-li a[wen-active]:after {             -webkit-transition: all ${this._duration}ms linear;             -moz-transition: all ${this._duration}ms linear;             -ms-transition: all ${this._duration}ms linear;             -o-transition: all ${this._duration}ms linear;             transition: all ${this._duration}ms linear;         }         .wen-menu-li a[wen-expand]:after {             -webkit-transform: scale(1.3) rotate(90deg);             -moz-transform: scale(1.3) rotate(90deg);             -ms-transform: scale(1.3) rotate(90deg);             -o-transform: scale(1.3) rotate(90deg);             transform: scale(1.3) rotate(90deg);         }         .wen-menu-li a[wen-collapse]:after {             -webkit-transform: scale(1.3) rotate(180deg);             -moz-transform: scale(1.3) rotate(180deg);             -ms-transform: scale(1.3) rotate(180deg);             -o-transform: scale(1.3) rotate(180deg);             transform: scale(1.3) rotate(180deg);         }         .wen-menu-li a[wen-icon]:after {             content: '▷';             position: absolute;             right: 5px;             font-weight: bold;         }         .wen-menu-li a[wen-active]:after {             content: '▷';             position: absolute;             right: 5px;             font-weight: bold;         }         .wen-menu-first {             padding-left: 15px !important;         }         .wen-menu-li a[wen-active], .wen-active {             color: white;         }         .wen-menu-li a[wen-active].wen-menu-first, .wen-active.wen-menu-first {             border-left: 3px solid white;         }     `;     if (!head) {         head = document.body;     }     head.append(style);     return this; } 三、Example-Code

(1)html文件

<!doctype html> <html lang="en"> <head>     <meta charset="UTF-8">     <meta name="viewport"           content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">     <meta http-equiv="X-UA-Compatible" content="ie=edge">     <title>说明文档</title>     <script src="/js/canvas/menu.js"></script>     <style>         * {             padding: 0px;             margin: 0px;             border-spacing: 0px;             list-style: none;         }         body {             min-height: 100vh;             padding: 0px;             margin: 0px;         }         .readme-title {             background: rgba(0, 0, 50, 0.3);             width: 100%;             display: flex;             justify-content: center;             align-items: center;             padding: 20px;             -webkit-box-sizing: border-box;             -moz-box-sizing: border-box;             box-sizing: border-box;         }         .readme-body {             width: 100%;             height: calc(100% - 75px);             display: flex;             justify-content: start;         }         .readme-menu-box {             width: 250px;             height: 100%;             position: fixed;             left: 0px;             top: 0px;             background: rgba(100, 10, 10, 0.2);             overflow: auto;         }     </style> </head> <body> <div class="readme-body">     <div class="readme-menu-box">         <div class="readme-title">             <h2>目录</h2>         </div>     </div> </div> </body> </html>

(2)JS代码

a、菜单列表

let menuOptions = [{                     text: "导入数据列表",                     subs: [                         {                             text: "全部数据",                             attributes: {                                 "data-url": "",                             },                             subs: [                                 {                                     text: "消费金额",                                     attributes: {                                         "data-url": "",                                     }                                 }, {                                     text: "放款金额",                                     attributes: {                                         "data-url": "",                                     }                                 }, {                                     text: "返佣金额",                                     attributes: {                                         "data-url": "",                                     }                                 }, {                                     text: "导入数据",                                     attributes: {                                         "data-url": "",                                     }                                 }, {                                     text: "查看",                                     attributes: {                                         "data-url": "",                                     }                                 }, {                                     text: "编辑",                                     attributes: {                                         "data-url": "",                                     }                                 }                             ]                         }, {                             text: "消费金额",                             attributes: {                                 "data-url": "",                             }                         }, {                             text: "放款金额",                             attributes: {                                 "data-url": "",                             }                         }, {                             text: "返佣金额",                             attributes: {                                 "data-url": "",                             }                         }, {                             text: "导入数据",                             attributes: {                                 "data-url": "",                             }                         }, {                             text: "查看",                             attributes: {                                 "data-url": "",                             }                         }, {                             text: "编辑",                             attributes: {                                 "data-url": "",                             }                         }                     ]                 }, {                     text: "异常数据列表",                     subs: []                 }, {                     text: "数据修正",                     subs: []                 }, {                     text: "修正审核-客服经理",                     subs: []                 }, {                     text: "修正审核-财务",                     subs: []                 }, {                     text: "导入日志",                     subs: []                 }]

b、菜单实例化 

window.onload = function () {             new WenMenu({                 ele: document.querySelector('.readme-menu-box'), // 菜单插入的位置                 menus: menuOptions,                 event: function (e) { }, // 菜单最底端点击事件触发                 attributes: {}, // 最外层ul属性设置                 menuHeight: 35, // 每个菜单项的高度                 autoCollapse: true, // 是否自动收起无活动菜单             })         };



js实现 菜单 菜单工具栏 工具 工具栏 js

需要 登录 后方可回复, 如果你还没有账号请 注册新账号