前言
在上期的LayUI基本元素之树形菜单案例实现的博客中我们了解了关于LayUI基本元素中的树形菜单的使用,这期博客基于上一期博客的基础上我们来实现选项卡功能的实现,在项目中选项卡是我们的一个必备功能,让我们跟随这期博客一起去了解一下吧。
1. 了解选项卡功能
1.1 什么是选项卡
选项卡(Tabs)是现代网络浏览器中常见的功能,它允许用户在同一个浏览器窗口中同时打开和浏览多个网页。每个选项卡都代表着一个独立的网页,在用户之间相互隔离,但仍然可以通过切换选项卡来方便地在它们之间进行导航。
1.2 选项卡的功能
- 通过使用选项卡,您可以同时访问多个网站,而无需打开多个浏览器窗口或混乱地在同一个窗口中切换不同的页面。您可以轻松地在选项卡之间切换,通过单击标签或使用快捷键(如Ctrl+Tab)在标签之间进行导航。
- 选项卡功能还允许用户以并行的方式处理多个任务和浏览多个信息源。您可以在一个选项卡中阅读新闻,同时在另一个选项卡中查找资料,而不会中断或丢失任何正在进行的工作。
1.3 如何使用LayUI实现选项卡功能
- 引入LayUI库:在HTML文件中,使用
<link>
标签引入LayUI的CSS文件和js文件。 - 创建选项卡容器:在HTML文件中创建一个容器来放置选项卡内容。(在jsp文件中定义对应的选项卡容器)
- 初始化选项卡组件:在HTML文件中使用JavaScript代码初始化选项卡组件。(编写js代码实现功能样式)
- 编写后端java代码:编写对应的类的java代码从数据库中实现项目对应的功能。
- 初始化选项卡组件:在HTML文件中使用JavaScript代码初始化选项卡组件。(根据个人需求操作)
2. 案例演示:在项目中实现选项卡功能
2.1 去LayUI旧版官网中找到对应的代码复制到项目中
我们选择的是动态操作的选项卡,将选择的部分复制到项目的对应位置,将一些不必要的代码给删除掉(下面是我整理后的jsp代码)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ include file="common/header.jsp"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>后台主界面</title> </head> <body> <div class="layui-layout layui-layout-admin"> <div class="layui-header"> <div class="layui-logo layui-hide-xs layui-bg-black">layout demo</div> <!-- 头部区域(可配合layui 已有的水平导航) --> <ul class="layui-nav layui-layout-left"> <!-- 移动端显示 --> <li class="layui-nav-item layui-show-xs-inline-block layui-hide-sm" lay-header-event="menuLeft"><i class="layui-icon layui-icon-spread-left"></i></li> <!-- Top导航栏 --> <li class="layui-nav-item layui-hide-xs"><a href="">nav 1</a></li> <li class="layui-nav-item layui-hide-xs"><a href="">nav 2</a></li> <li class="layui-nav-item layui-hide-xs"><a href="">nav 3</a></li> <li class="layui-nav-item"><a href="javascript:;">nav groups</a> <dl class="layui-nav-child"> <dd> <a href="">menu 11</a> </dd> <dd> <a href="">menu 22</a> </dd> <dd> <a href="">menu 33</a> </dd> </dl></li> </ul> <!-- 个人头像及账号操作 --> <ul class="layui-nav layui-layout-right"> <li class="layui-nav-item layui-hide layui-show-md-inline-block"> <a href="javascript:;"> <img src="//tva1.sinaimg.cn/crop.0.0.118.118.180/5db11ff4gw1e77d3nqrv8j203b03cweg.jpg" class="layui-nav-img"> tester </a> <dl class="layui-nav-child"> <dd> <a href="">Your Profile</a> </dd> <dd> <a href="">Settings</a> </dd> <dd> <a href="login.jsp">Sign out</a> </dd> </dl> </li> <li class="layui-nav-item" lay-header-event="menuRight" lay-unselect> <a href="javascript:;"> <i class="layui-icon layui-icon-more-vertical"></i> </a> </li> </ul> </div> <div class="layui-side layui-bg-black"> <div class="layui-side-scroll"> <!-- 左侧导航区域(可配合layui已有的垂直导航) --> <ul id="menu" class="layui-nav layui-nav-tree" lay-filter="menu"> <li class="layui-nav-item layui-nav-itemed"><a class="" href="javascript:;">menu group 1</a> <dl class="layui-nav-child"> <dd> <a href="javascript:;">menu 1</a> </dd> <dd> <a href="javascript:;">menu 2</a> </dd> <dd> <a href="javascript:;">menu 3</a> </dd> <dd> <a href="">the links</a> </dd> </dl></li> <li class="layui-nav-item"><a href="javascript:;">menu group 2</a> <dl class="layui-nav-child"> <dd> <a href="javascript:;">list 1</a> </dd> <dd> <a href="javascript:;">list 2</a> </dd> <dd> <a href="">超链接</a> </dd> </dl></li> <li class="layui-nav-item"><a href="javascript:;">click menu item</a></li> <li class="layui-nav-item"><a href="">the links</a></li> </ul> </div> </div> <div class="layui-body"> <!-- 内容主体区域 --> <div class="layui-tab" lay-filter="demo" lay-allowclose="true"> <ul class="layui-tab-title"> <li class="layui-this" lay-id="11">网站设置</li> <li lay-id="22">用户管理</li> <li lay-id="33">权限分配</li> <li lay-id="44">商品管理</li> <li lay-id="55">订单管理</li> </ul> <div class="layui-tab-content"> <div class="layui-tab-item layui-show">内容1</div> <div class="layui-tab-item">内容2</div> <div class="layui-tab-item">内容3</div> <div class="layui-tab-item">内容4</div> <div class="layui-tab-item">内容5</div> </div> </div> </div> <div class="layui-footer"> <!-- 底部固定区域 --> 底部固定区域 </div> </div> <script> //JS var element,layer,util,$; layui.use(['element', 'layer', 'util'], function(){ element = layui.element ,layer = layui.layer ,util = layui.util ,$ = layui.$; //发送请求 $.ajax({ url:"${pageContext.request.contextPath }/permission.action?methodName=menus", dataType:'json', success:function(data){ console.log(data); //定义变量拼接 var htmlstr = ''; //遍历 $.each(data,function(i,n){ //拼接 htmlstr += '<li class="layui-nav-item layui-nav-itemed">'; htmlstr += '<a class="" href="javascript:;">'+n.text+' </a>' ; //判断是否有子选择菜单 if (n.hasChildren) { //获取子选项 var children=n.children; htmlstr += '<dl class="layui-nav-child">' ; //遍历子选项 $.each(children,function(idx,node){ // htmlstr += '<dd><a href="javascript:;" onclick="openTab(\''+node.text+'\',\''+node.+'\',\'\')">'+node.text+'</a></dd>' }); htmlstr += '</dl>' ; } htmlstr += '</li>' }); //设置树形菜单的代码 $("#menu").html(htmlstr); element.render('menu');//渲染树形菜单 } }); }); //title:选项卡名;content:显示的内容;id:选项卡id function openTab(title,content,id){ //添加选项卡 element.tabAdd('demo', { title: title//选项卡所展示的名称 ,content:content//选项卡所展示的内容 ,id: id //选项卡的id }) } </script> </body> </html>
效果图如下所示
2.2 编写对应的后端代码实现项目对应的功能(优化PermissionDao类的方法)
package com.YX.dao; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.YX.entity.Permission; import com.fasterxml.jackson.databind.ObjectMapper; import com.zking.util.BaseDao; import com.zking.util.BuildTree; import com.zking.util.PageBean; import com.zking.util.TreeVo; /** * Dao方法类 * * @author 君易--鑨 2023年7月11日下午8:01:00 * */ public class PermissionDao extends BaseDao<Permission> { /** * 获取树形菜单选项 * * @param permission * @param pageBean * @return * @throws Exception */ public List<Permission> list(Permission permission, PageBean pageBean) throws Exception { String sql = "select * from t_oa_permission"; return super.executeQuery(sql, Permission.class, pageBean); } // 将数据库中查询出的平级数据,转换成有父子关系的数据 /** * 有父子关系结果的方法 * * @param permission * @param pageBean * @return * @throws Exception */ public List<TreeVo<Permission>> menus(Permission permission, PageBean pageBean) throws Exception { // 实例化一个有父子关系的集合 List<TreeVo<Permission>> lst = new ArrayList<TreeVo<Permission>>(); // 重新调用方法获取选项集合 List<Permission> list = this.list(permission, pageBean); // 遍历 for (Permission p : list) { // 实例化树形菜单工具类 TreeVo<Permission> vo = new TreeVo<>(); // 设置属性 vo.setId(p.getId() + ""); vo.setText(p.getName()); vo.setParentId(p.getPid() + ""); // 新建一个map集合存储对应子选项对应的属性 Map<String, Object> map=new HashMap<String, Object>(); // 将对应的属性添加到map集合中 map.put("self", p); // 再将map集合方法放到vo对象中 vo.setAttributes(map); lst.add(vo); } return BuildTree.buildList(lst, "-1"); } // 测试 public static void main(String[] args) { PermissionDao pd = new PermissionDao(); try { List<TreeVo<Permission>> list = pd.menus(null, null); ObjectMapper om = new ObjectMapper(); System.out.println(om.writeValueAsString(list)); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
主要是优化PermissionDao类的方法中的menus()方法将子选项的对应属性存储到map集合中,再将map集合添加到vo对象中,方便在页面上能获取到然后将jsp进行进一步优化,编写js代码实现效果。(下面是js代码)
2.3 编写对应的JS代码(实现效果)
下面是优化过的js代码,但不是最完善的,还需要进行进一步完善(还没有去重复),下面是js代码和演示效果。
<script> //JS var element,layer,util,$; layui.use(['element', 'layer', 'util'], function(){ element = layui.element ,layer = layui.layer ,util = layui.util ,$ = layui.$; //发送请求 $.ajax({ url:"${pageContext.request.contextPath }/permission.action?methodName=menus", dataType:'json', success:function(data){ console.log(data); //定义变量拼接 var htmlstr = ''; //遍历 $.each(data,function(i,n){ //拼接 htmlstr += '<li class="layui-nav-item layui-nav-itemed">'; htmlstr += '<a class="" href="javascript:;">'+n.text+' </a>' ; //判断是否有子选择菜单 if (n.hasChildren) { //获取子选项 var children=n.children; htmlstr += '<dl class="layui-nav-child">' ; //遍历子选项 $.each(children,function(idx,node){ htmlstr += '<dd><a href="javascript:;" onclick="openTab(\''+node.text+'\',\''+node.attributes.self.url+'\',\''+node.id+'\')">'+node.text+'</a></dd>' }); htmlstr += '</dl>' ; } htmlstr += '</li>' }); //设置树形菜单的代码 $("#menu").html(htmlstr); element.render('menu');//渲染树形菜单 } }); }); //title:选项卡名;content:显示的内容;id:选项卡id function openTab(title,content,id){ //添加选项卡 element.tabAdd('demo', { title: title//选项卡所展示的名称 ,content:content//选项卡所展示的内容 ,id: id //选项卡的id }) } </script>
页面演示结果
就如演示所示,到我们两次选择同一个子选项时选项卡会重复添加一个选项,并且不能显示指定选项的内容,下面我们将进行又一次优化,优化上述的问题。
2.4 进一步优化js代码(实现去重和优化效果)
下面的js代码是实现重名的选项名不会新增选项,重名的选项卡被选中显示指定内容。
<script> //JS var element,layer,util,$; layui.use(['element', 'layer', 'util'], function(){ element = layui.element ,layer = layui.layer ,util = layui.util ,$ = layui.$; //发送请求 $.ajax({ url:"${pageContext.request.contextPath }/permission.action?methodName=menus", dataType:'json', success:function(data){ console.log(data); //定义变量拼接 var htmlstr = ''; //遍历 $.each(data,function(i,n){ //拼接 htmlstr += '<li class="layui-nav-item layui-nav-itemed">'; htmlstr += '<a class="" href="javascript:;">'+n.text+' </a>' ; //判断是否有子选择菜单 if (n.hasChildren) { //获取子选项 var children=n.children; htmlstr += '<dl class="layui-nav-child">' ; //遍历子选项 $.each(children,function(idx,node){ htmlstr += '<dd><a href="javascript:;" onclick="openTab(\''+node.text+'\',\''+node.attributes.self.url+'\',\''+node.id+'\')">'+node.text+'</a></dd>' }); htmlstr += '</dl>' ; } htmlstr += '</li>' }); //设置树形菜单的代码 $("#menu").html(htmlstr); element.render('menu');//渲染树形菜单 } }); }); //title:选项卡名;content:显示的内容;id:选项卡id function openTab(title,content,id){ //获取选中的子选项 var $node = $('li[lay-id="'+id+'"]'); if ($node.length == 0) { //添加选项卡 element.tabAdd('demo', { title : title//选项卡所展示的名称 , content : content//选项卡所展示的内容 , id : id //选项卡的id }) } //切换到指定Tab项 element.tabChange('demo', id); //切换到:用户管理 } </script>
页面实现的效果如下图示
这就是最终展现出来的效果,我们可以根据自己的需求去修改一些显示的样式效果,那些有我们自己去探索吧。
3. 拓展(项目重构思想)
这里给大家分享一个新知识,就是我们的项目重构思想,可以说是企业里的一项基本要求。就是我们一般的js代码文件都会放在/WebContent/static的js文件夹下,然后我们的一些页面的jsp文件中都会有一些js代码,因此我们要在js文件夹下创建对应的文件由于存储对应jsp文件的js代码,利于往后的维护和修改。(效果图如下)
YX_login.js文件代码
layui.use([ 'layer', 'jquery' ], function() { var layer = layui.layer, $ = layui.jquery; //设置点击事件 $("#login").click(function(){ //发送ajax请求 $.ajax({ url:'user.action?methodName=login', dataType:'json', data:{ loginName:$("#username").val(), pwd:$("#password").val(), }, method:'post', success:function(data){ if (data) { layer.alert('恭喜'+data.name+'登陆成功',{icon:6}); location.href='YX_main.jsp'; }else{ layer.alert('账号密码错误',{icon:5}); } } }); layer.msg($("#inputId").val()) }); });
YX_main.js代码
var element,layer,util,$; layui.use(['element', 'layer', 'util'], function(){ element = layui.element ,layer = layui.layer ,util = layui.util ,$ = layui.$; //发送请求 $.ajax({ url:"permission.action?methodName=menus", dataType:'json', success:function(data){ console.log(data); //定义变量拼接 var htmlstr = ''; //遍历 $.each(data,function(i,n){ //拼接 htmlstr += '<li class="layui-nav-item layui-nav-itemed">'; htmlstr += '<a class="" href="javascript:;">'+n.text+' </a>' ; //判断是否有子选择菜单 if (n.hasChildren) { //获取子选项 var children=n.children; htmlstr += '<dl class="layui-nav-child">' ; //遍历子选项 $.each(children,function(idx,node){ htmlstr += '<dd><a href="javascript:;" onclick="openTab(\''+node.text+'\',\''+node.attributes.self.url+'\',\''+node.id+'\')">'+node.text+'</a></dd>' }); htmlstr += '</dl>' ; } htmlstr += '</li>' }); //设置树形菜单的代码 $("#menu").html(htmlstr); element.render('menu');//渲染树形菜单 } }); }); //title:选项卡名;content:显示的内容;id:选项卡id function openTab(title,content,id){ //获取选中的子选项 var $node = $('li[lay-id="'+id+'"]'); if ($node.length == 0) { //添加选项卡 element.tabAdd('demo', { title : title//选项卡所展示的名称 , content : content//选项卡所展示的内容 , id : id //选项卡的id }) } //切换到指定Tab项 element.tabChange('demo', id); //切换到:用户管理 }
注意事项:
- 新建的js文件中不支持${....}表达式,所以不能用${....}表达式拼接绝对路径,所以我们在公共文件中定义一个base标签,这样只要在jsp页面上引入公共文件即可,就不用拼接绝对路径了。
公共文件(header.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html "> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <!-- 引入 layui.css --> <link rel="stylesheet" href="${pageContext.request.contextPath }/static/js/layui/css/layui.css"> <!-- 引入 layui.js --> <script src="${pageContext.request.contextPath }/static/js/layui/layui.js"></script> <base href="${pageContext.request.contextPath }/" />
2.在jsp页面上记得导入对应的js文件。
所以我们就不用担心说会出现文件没有拼接绝对路径找不到文件的情况了。
演示项目运行
结束语
这期的博客分享就到这里了,喜欢的老铁三连一波关注下期博客。