JS实现左侧菜单工具栏

本文实例为大家分享了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 = '--'; }icon.innerHTML = this._iconHTML; a.append(icon); a.innerHTML += `${this._text}`; 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 = truemenuNode._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属性 * @paramWenMenuNode menuNode * @returnWenMenuNode */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; }; /** * 创建元素 * @paramtagName * @paramattributes * @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 = https://www.it610.com/article/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 = https://www.it610.com/article/valueStr; }return value; } if (attributes) {Object.keys(attributes).forEach((name) => {let value = https://www.it610.com/article/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文件
说明文档 - 锐客网* {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; }目录

(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: []}]

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    推荐阅读