layui动态渲染生成左侧3级菜单的方法(根据后台返回数据)


Posted in Javascript onSeptember 23, 2019

声明:这里非常感谢闲心大神,开源了非常好用的前端UI框架,layui,如有侵权请联系我。当然闲心在2.0版本的layuiAdmin已经支持了,不过是收费版的,需要的同学可以自行购买,网址:http://www.layui.com/admin/pro/

本人在做管理后台事用到了左侧的导航列表,但是管理后台进来的菜单是根据不同账户的权限,显示不同的菜单。这时候需要动态的渲染左侧的列表。但是1.0版本只是更新到2级菜单,不满足如下图的3级菜单需求,只能自己动手,改造源码

layui动态渲染生成左侧3级菜单的方法(根据后台返回数据)

话不多说,上代码:

1.html部分,我需要一个容器用于渲染菜单

<div class="layui-side layui-bg-black" id="admin-side">
  <div class="layui-side-scroll">
  <ul class="layui-nav layui-nav-tree" id="nav" lay-filter="demo"></ul>
  </div>
 </div>

接下来是插件以及相关JS,css引入 ,注意:路径问题,换成自己本地的路径

<link rel="stylesheet" href="../layui/css/layui.css" rel="external nofollow" >
<script src="../lib/jquery-1.12.2.js" type="text/javascript" charset="utf-8"></script>
<script src="../layui/layui.js"></script>

2.js部分

<script>
 //监听选中页签添加样式
 layui.config({
 base: '../layui/' //navbar组件js所在目录
 }).use('navbar', function() {
 var navbar = layui.navbar();
 navbar.set({
  elem: '#nav',
  url: "../layui/nav2.json" //数据源地址,我用了本地写的json数据
 });
 navbar.render();
 //下面的部分不是必须的
 navbar.on('click(demo)', function(data) {
  console.log(data.elem);
  console.log(data.field.title);//标题
  console.log(data.field.icon);//图标
  console.log(data.field.href);//调转地址
  layer.msg(data.field.href);
 });
 
 //给选中的页签添加选中样式(解决刷新失效问题)
 var url = window.location.href.replace("//", "");
 var relUrl = url.substring(url.lastIndexOf("/") + 1);
 //去掉参数部分
 if (relUrl.indexOf("?") != -1) {
  relUrl = relUrl.split("?")[0];
 }
 $("#leftNavbar a").each(function () {
  var that = this;
 if ($(that).attr("href") == relUrl) {
  $(that).parent().addClass("layui-this");
  $(that).parents("li:eq(0)").addClass("layui-nav-itemed");
  var nodes = $(that).parents("li:eq(0)").find("a .layui-nav-more");
  if (nodes.length > 0) {
  nodes.each(function () {
   if ($(this).parents("dd:eq(0)").find("[href='" + relUrl + 
  "']").length > 0) {
   $(this).parent().parent().addClass("layui-nav-itemed");
   }
  });
  }
  }
 });
 
 });
 </script>

重点来了:navbar,js

/**
 * navbar.js
 * @author 御风 <1945199284@qq.com>
 */
layui.define(['element', 'common'], function (exports) {
 "use strict";
 var $ = layui.jquery,
 layer = parent.layer === undefined ? layui.layer : parent.layer,
 element = layui.element,
 common = layui.common,
 cacheName = 'tb_navbar';
 
 var Navbar = function () {
 /**
  * 默认配置
  */
 this.config = {
  elem: undefined, //容器
  data: undefined, //数据源
  url: undefined, //数据源地址
  type: 'GET', //读取方式
  cached: false, //是否使用缓存
  spreadOne: false //设置是否只展开一个二级菜单
 };
 this.v = '1.0.0';
 };
 //渲染
 Navbar.prototype.render = function () {
 var _that = this;
 var _config = _that.config;
 if (typeof (_config.elem) !== 'string' && typeof (_config.elem) !== 'object') {
  common.throwError('Navbar error: elem参数未定义或设置出错,具体设置格式请参考文档API.');
 }
 var $container;
 if (typeof (_config.elem) === 'string') {
  $container = $('' + _config.elem + '');
 }
 if (typeof (_config.elem) === 'object') {
  $container = _config.elem;
 }
 if ($container.length === 0) {
  common.throwError('Navbar error:找不到elem参数配置的容器,请检查.');
 }
 if (_config.data === undefined && _config.url === undefined) {
  common.throwError('Navbar error:请为Navbar配置数据源.')
 }
 if (_config.data !== undefined && typeof (_config.data) === 'object') {
  var html = getHtml(_config.data);
  $container.html(html);
  element.init();
  _that.config.elem = $container;
 } else {
  if (_config.cached) {
  var cacheNavbar = layui.data(cacheName);
  if (cacheNavbar.navbar === undefined) {
   $.ajax({
   type: _config.type,
   url: _config.url,
   async: false, //_config.async,
   dataType: 'json',
   success: function (result, status, xhr) {
    //添加缓存
    layui.data(cacheName, {
    key: 'navbar',
    value: result
    });
    var html = getHtml(result);
    $container.html(html);
    element.init();
   },
   error: function (xhr, status, error) {
    common.msgError('Navbar error:' + error);
   },
   complete: function (xhr, status) {
    _that.config.elem = $container;
   }
   });
  } else {
   var html = getHtml(cacheNavbar.navbar);
   $container.html(html);
   element.init();
   _that.config.elem = $container;
  }
  } else {
  //清空缓存
  layui.data(cacheName, null);
  $.ajax({
   type: _config.type,
   url: _config.url,
   async: false, //_config.async,
   dataType: 'json',
   success: function (result, status, xhr) {
   var html = getHtml(result);
   $container.html(html);
   element.init();
   },
   error: function (xhr, status, error) {
   common.msgError('Navbar error:' + error);
   },
   complete: function (xhr, status) {
   _that.config.elem = $container;
   }
  });
  }
 }
 
 //只展开一个二级菜单
 if (_config.spreadOne) {
  var $ul = $container.children('ul');
  $ul.find('li.layui-nav-item').each(function () {
  $(this).on('click', function () {
   $(this).siblings().removeClass('layui-nav-itemed');
  });
  });
 }
 return _that;
 };
 /**
 * 配置Navbar
 * @param {Object} options
 */
 Navbar.prototype.set = function (options) {
 var that = this;
 that.config.data = undefined;
 $.extend(true, that.config, options);
 return that;
 };
 /**
 * 绑定事件
 * @param {String} events
 * @param {Function} callback
 */
 Navbar.prototype.on = function (events, callback) {
 var that = this;
 var _con = that.config.elem;
 if (typeof (events) !== 'string') {
  common.throwError('Navbar error:事件名配置出错,请参考API文档.');
 }
 var lIndex = events.indexOf('(');
 var eventName = events.substr(0, lIndex);
 var filter = events.substring(lIndex + 1, events.indexOf(')'));
 if (eventName === 'click') {
  if (_con.attr('lay-filter') !== undefined) {
  _con.children('ul').find('li').each(function () {
   var $this = $(this);
   if ($this.find('dl').length > 0) {
   var $dd = $this.find('dd').each(function () {
    $(this).on('click', function () {
    var $a = $(this).children('a');
    var href = $a.data('url');
    var icon = $a.children('i:first').data('icon');
    var title = $a.children('cite').text();
    var data = {
     elem: $a,
     field: {
     href: href,
     icon: icon,
     title: title
     }
    }
    callback(data);
    });
   });
   } else {
   $this.on('click', function () {
    var $a = $this.children('a');
    var href = $a.data('url');
    var icon = $a.children('i:first').data('icon');
    var title = $a.children('cite').text();
    var data = {
    elem: $a,
    field: {
     href: href,
     icon: icon,
     title: title
    }
    }
    callback(data);
   });
   }
  });
  }
 }
 };
 /**
 * 清除缓存
 */
 Navbar.prototype.cleanCached = function () {
 layui.data(cacheName, null);
 };
 /**
 * 获取html字符串
 * @param {Object} data
 */
 function getHtml(data) {
 var ulHtml = '<ul class="layui-nav layui-nav-tree beg-navbar">';
 for (var i = 0; i < data.length; i++) {
  if (data[i].spread) {
  ulHtml += '<li class="layui-nav-item layui-nav-itemed">';
  } else {
  ulHtml += '<li class="layui-nav-item">';
  }
  if (data[i].children !== undefined && data[i].children !== null && data[i].children.length > 0) {
  ulHtml += '<a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" >' + data[i].title;
  ulHtml += '<span class="layui-nav-more"></span>';
  ulHtml += '</a>';
  ulHtml += '<dl class="layui-nav-child">';
  //二级菜单
  for (var j = 0; j < data[i].children.length; j++) {
   //是否有孙子节点
   if (data[i].children[j].children !== undefined && data[i].children[j].children !== null && data[i].children[j].children.length > 0) {
   ulHtml += '<dd>';
   ulHtml += '<a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" >' + data[i].children[j].title;
   ulHtml += '<span class="layui-nav-more"></span>';
   ulHtml += '</a>';
   //三级菜单
   ulHtml += '<dl class="layui-nav-child">';
    var grandsonNodes = data[i].children[j].children;
    for (var k = 0; k < grandsonNodes.length; k++) {
    ulHtml += '<dd>';
    ulHtml += '<a href="'+ grandsonNodes[k].href +'" rel="external nofollow" >' + grandsonNodes[k].title + '</a>';
    ulHtml += '</dd>';
    }
   ulHtml += '</dl>';
   ulHtml += '</dd>';
   }else{
   ulHtml += '<dd>';
   ulHtml += '<a href="'+data[i].children[j].href+'" rel="external nofollow" >' + data[i].children[j].title;
   ulHtml += '</a>';
   ulHtml += '</dd>';
   }
   //ulHtml += '<dd title="' + data[i].children[j].title + '">'; 
  }
  ulHtml += '</dl>';
  } else {
  var dataUrl = (data[i].href !== undefined && data[i].href !== '') ? 'data-url="' + data[i].href + '"' : '';
  //ulHtml += '<a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" ' + dataUrl + '>';
  ulHtml += '<a href="' + data[i].href + '" rel="external nofollow" ' + dataUrl + '>';
  if (data[i].icon !== undefined && data[i].icon !== '') {
   if (data[i].icon.indexOf('fa-') !== -1) {
   ulHtml += '<i class="fa ' + data[i].icon + '" aria-hidden="true" data-icon="' + data[i].icon + '"></i>';
   } else {
   ulHtml += '<i class="layui-icon" data-icon="' + data[i].icon + '">' + data[i].icon + '</i>';
   }
  }
  ulHtml += '<cite>' + data[i].title + '</cite>';
  ulHtml += '</a>';
  }
  ulHtml += '</li>';
 }
 ulHtml += '</ul>';
 
 return ulHtml;
 }
 
 var navbar = new Navbar();
 
 exports('navbar', function (options) {
 return navbar.set(options);
 });
});

公共配置common.js

/**
 * common.js
 * @author 御风 <1945199284@qq.com>
 */
layui.define(['layer'], function(exports) {
 "use strict";
 
 var $ = layui.jquery,
 layer = layui.layer;
 
 var common = {
 /**
  * 抛出一个异常错误信息
  * @param {String} msg
  */
 throwError: function(msg) {
  throw new Error(msg);
  return;
 },
 /**
  * 弹出一个错误提示
  * @param {String} msg
  */
 msgError: function(msg) {
  layer.msg(msg, {
  icon: 5
  });
  return;
 }
 };
 
 exports('common', common);
});

3.返回数据json格式

[
 {
 "title": "首页",
 "icon": " ",
 "spread": true,
 "href": ""
 },
 {
 "title": "一级导航",
 "icon": "fa-stop-circle",
 "spread": true,
 "href": "http://www.baidu.com",
 "children": [
 {
 "title": "二级导航",
 "icon": "",
 "href": "lala.html",
 "spread": true,
 "children": [
  {
  "title": "三级导航",
  "icon": " ",
  "href": "button.html"
  },
  {
  "title": "三级导航",
  "icon": " ",
  "href": "buttwswon.html"
  }
 ]
 }
 ]
 },
 {
 "title": "一级导航",
 "icon": "fa-stop-circle",
 "spread": true,
 "href": "http://www.baidu.com"
 
 },
 {
 "title": "一级导航",
 "icon": "fa-stop-circle",
 "spread": true,
 "href": "http://www.baidu.com"
 
 },
 {
 "title": "一级导航",
 "icon": "fa-stop-circle",
 "spread": true,
 "href": "http://www.baidu.com"
 
 }
]

总结:渲染dom,只要的思路就是用了2次for循环,遍历后台返回的数据。

以上这篇layui动态渲染生成左侧3级菜单的方法(根据后台返回数据)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
在JavaScript中遭遇级联表达式陷阱
Mar 08 Javascript
jquery 指南/入门基础
Nov 30 Javascript
javascript 控制input只允许输入的各种指定内容
Jun 19 Javascript
jquery实现textarea 高度自适应
Mar 11 Javascript
微信小程序 数据交互与渲染实例详解
Jan 21 Javascript
Bootstrap 响应式实用工具实例详解
Mar 29 Javascript
Mongoose中document与object的区别示例详解
Sep 18 Javascript
vue动态绑定组件子父组件多表单验证功能的实现代码
May 14 Javascript
新手必须知的Node.js 4个JavaScript基本概念
Sep 16 Javascript
webpack3升级到webpack4遇到问题总结
Sep 30 Javascript
vue props 一次传多个值实例
Jul 22 Javascript
Nuxt的路由配置和参数传递方式
Nov 06 Javascript
layui树形菜单动态遍历的例子
Sep 23 #Javascript
Vue+elementui 实现复杂表头和动态增加列的二维表格功能
Sep 23 #Javascript
优雅的使用javascript递归画一棵结构树示例代码
Sep 22 #Javascript
Webpack按需加载打包chunk命名的方法
Sep 22 #Javascript
jquery.tagsinput.js实现记录checkbox勾选的顺序
Sep 21 #jQuery
vue2.0+SVG实现音乐播放圆形进度条组件
Sep 21 #Javascript
js+springMVC 提交数组数据到后台的实例
Sep 21 #Javascript
You might like
精致的人儿就要挑杯子喝咖啡
2021/03/03 冲泡冲煮
解决php中Cannot send session cache limiter 的问题的方法
2007/04/27 PHP
wordpress之wp-settings.php
2007/08/17 PHP
php设计模式 Adapter(适配器模式)
2011/06/26 PHP
php读取文件内容的方法汇总
2015/01/24 PHP
PHP socket 模拟POST 请求实例代码
2016/07/18 PHP
PHP二维数组去重实例分析
2016/11/18 PHP
微信推送功能实现方式图文详解
2019/07/12 PHP
用ADODB.Stream转换
2007/01/22 Javascript
jQuery Validation插件remote验证方式的Bug解决
2010/07/01 Javascript
jQuery :nth-child前有无空格的区别分析
2011/07/11 Javascript
js拖动div 当鼠标移动时整个div也相应的移动
2013/11/21 Javascript
Javascript验证上传图片大小[前台处理]
2014/07/18 Javascript
js+jquery常用知识点汇总
2015/03/03 Javascript
微信小程序新增的拖动组件movable-view使用教程
2017/05/20 Javascript
微信分享调用jssdk实例
2017/06/08 Javascript
jQuery查找和过滤_动力节点节点Java学院整理
2017/07/04 jQuery
React Native中导航组件react-navigation跨tab路由处理详解
2017/10/31 Javascript
深入理解JavaScript的值传递和引用传递
2018/10/24 Javascript
Fetch超时设置与终止请求详解
2019/05/18 Javascript
如何在Node和浏览器控制台中打印彩色文字
2020/01/09 Javascript
Vue优化:常见会导致内存泄漏问题及优化详解
2020/08/04 Javascript
IDEA配置jQuery, $符号不再显示黄色波浪线的问题
2020/10/09 jQuery
Python之PyUnit单元测试实例
2014/10/11 Python
Python 搭建Web站点之Web服务器与Web框架
2016/11/06 Python
使用pandas中的DataFrame数据绘制柱状图的方法
2018/04/10 Python
一文了解Python并发编程的工程实现方法
2019/05/31 Python
python用opencv 图像傅里叶变换
2021/01/04 Python
J2EE包括哪些技术
2016/11/25 面试题
致跳远、跳高运动员广播稿
2014/01/09 职场文书
《三个小伙伴》教学反思
2014/04/11 职场文书
小学趣味运动会加油稿
2014/09/25 职场文书
工作批评与自我批评范文
2014/10/16 职场文书
新课程改革心得体会
2016/01/22 职场文书
Python opencv缺陷检测的实现及问题解决
2021/04/24 Python
Win10鼠标轨迹怎么开 Win10显示鼠标轨迹方法
2022/04/06 数码科技