WEB开发中前后台树形菜单的展示设计
在WEB开发中经常需要进行树形菜单的展示,本例通过不同角度的总结了如下三种实现方式:
- 通过JS的递归实现前端菜单DOM的动态创建
- 通过JSP的include指令结合JSTL表达式语言递归实现菜单的展示
- 通过扩展JSP的标签在后端实现菜单的DOM节点并响应给前端展示
针对第一种方法,可以采用JS的相关组件,或者使用JS的递归调用将服务端相应的数据组装成DOM节点内容,动态添加到菜单的Container中,网上的例子较多,在此不再赘述,本例就后两种方案进行讲解。
通过JSP的include指令结合JSTL表达式语言递归实现菜单的展示
由于JSP中的JSTL不支持递归,又不想在JSP中加入Java脚本,可以采用JSP动态包含的方式组装菜单,当前方案需要服务端将菜单列表组装成树形结构,具体算法如下:
主页面menu.jsp
<ul class="nav nav-list">
<c:if test="${not empty sessionScope.SESSION_MENUS}">
<c:forEach items="${sessionScope.SESSION_MENUS }" var="menu">
<%@include file="recursiveMenu.jsp"%>
</c:forEach>
</c:if>
</ul><!-- /.nav-list -->
递归调用页面recursiveMenu.jsp
<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<li>
<c:choose>
<c:when test="${empty menu.children }">
<a href="${menu.url }">
<i class="${menu.icon }"></i>
<span class="menu-text"> ${menu.name } </span>
</a>
</c:when>
<c:otherwise>
<a href="javascript:void(0);" class="dropdown-toggle">
<i class="${menu.icon }"></i>
<span class="menu-text"> ${menu.name } </span>
<b class="arrow icon-angle-down"></b>
<ul class="submenu">
<c:forEach items="${menu.children }" var="menu">
<c:set var="menu" value="${menu}" scope="request"/>
<jsp:include page="recursiveMenu.jsp"/>
</c:forEach>
</ul>
</a>
</c:otherwise>
</c:choose>
</li>
通过扩展JSP的标签在后端实现菜单的DOM节点并相应给前端展示
当前方案采用扩展JSP标签的方式实现具体实现方法如下
1、新建标签实现类MenuTa.java
package com.luwei.console.mg.tag; import java.io.IOException;
import java.util.List; import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import com.luwei.console.mg.constant.KeyConst;
import com.luwei.console.mg.entity.ext.MenuExt; /**
* <Description> 菜单标签<br>
*
* @author lu.wei<br>
* @email 1025742048@qq.com <br>
* @date 2016年12月25日 <br>
* @since V1.0<br>
* @see com.luwei.console.mg.tag <br>
*/
public class MenuTag extends TagSupport {
private Logger logger = LoggerFactory.getLogger(this.getClass()); /**
* serialVersionUID <br>
*/
private static final long serialVersionUID = -2755997672501044414L; @SuppressWarnings("unchecked")
@Override
public int doStartTag() throws JspException {
Object menusObj = pageContext.getSession().getAttribute(KeyConst.KEY_SESSION_MENUS);
if (null != menusObj) {
List<MenuExt> menus = (List<MenuExt>) menusObj;
String menuStr = assumbleMenuHtml(menus);
try {
pageContext.getOut().println(menuStr);
}
catch (IOException e) {
logger.error("菜单标签创建菜单出错:{} ", e.getMessage(), e);
}
}
return super.doStartTag();
} /**
* <Description> TODO<br>
*
* @author lu.wei<br>
* @email 1025742048@qq.com <br>
* @date 2016年12月25日 上午9:29:26 <br>
* @param menus
* @return <br>
*/
private String assumbleMenuHtml(List<MenuExt> menus) {
StringBuffer sb = new StringBuffer(""); if (!menus.isEmpty()) {
long activeMenuId = 1;
Object avtiveMenuIdObj = pageContext.getSession().getAttribute(KeyConst.SESSION_ACTIVE_MENU_ID);
if (null != avtiveMenuIdObj) {
activeMenuId = (Long) avtiveMenuIdObj;
}
for (MenuExt menu : menus) { if (menu.getId() == activeMenuId) {
sb.append("<li class='active'>");
}
else {
sb.append("<li>");
} boolean hasChild = false;
if (null != menu.getChildren() && !menu.getChildren().isEmpty()) {
hasChild = true;
}
if (hasChild) {
sb.append("<a href='#' class='dropdown-toggle'> ");
}
else {
String url = menu.getUrl();
if (StringUtils.isNotEmpty(url)) {
if (url.contains("?")) {
url = (url + "&mid=" + menu.getId());
}
else {
url = (url + "?mid=" + menu.getId());
}
}
sb.append("<a href='").append(url).append("'>");
} if (StringUtils.isNotEmpty(menu.getIcon())) {
sb.append("<i class='").append(menu.getIcon()).append("'></i>");
}
sb.append("<span class='menu-text'>").append(menu.getName()).append("</span>");
if (hasChild) {
sb.append("<b class='arrow icon-angle-down'></b>");
}
sb.append("</a>");
if (hasChild) {
sb.append("<ul class='submenu'>").append(assumbleMenuHtml(menu.getChildren())).append("</ul>");
}
sb.append("</li>");
}
}
return sb.toString();
}
}
2、配置标签
在项目的WEB-INFO目录下新建文件treeMenuAssum.tld
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
" http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.2</jspversion>
<shortname>menu</shortname>
<uri>http://www.luwei.com/web/ext/menus</uri>
<tag>
<name>menu</name>
<tagclass>com.luwei.console.mg.tag.MenuTag</tagclass>
</tag>
</taglib>
3、使用菜单标签
在JSP页面中直接使用新建标签
<%@ taglib prefix="menu" uri="http://www.luwei.com/web/ext/menus" %>
<menu:menu/>
总结
以上三种方式均能够实现后端服务的配置管理的无限树形菜单在前端显示出来,第一种方法服务端只需要将数据组装成前端需要的格式相应给前端,前端通过空间或者递归的方式动态创建DOM节点就可以了;二后两种方式采用纯Java相关的知识完全由服务端生成树形菜单,服务端会有一定的负载,同时采用JSP动态包含的方式,如果是在菜单中存在复杂逻辑的话不容易实现,因此推荐使用第一和第三中方案。
具体采用哪种方式可以根据各自项目进行选择,但是实现原理都是相同的。
WEB开发中前后台树形菜单的展示设计的更多相关文章
- web开发中前后端传值
在JavaScript中,页面与页面间的传值需要注意. 比如,我们通过url向下个页面进行传一个数字时,到下个页面进行解析出来后可能是一个字符串.这样会导致一个现象.调试时,发现我要传的值的确传过来了 ...
- web 开发之酷炫--- 酷炫展示
http://www.cnblogs.com/dsxniubility/p/4588560.html
- java web开发_购物车功能实现
java web开发_购物车功能实现 之前没有接触过购物车的东东,也不知道购物车应该怎么做,所以在查询了很多资料,总结一下购物车的功能实现. 查询的资料,找到三种方法: 1.用cookie实现购物车: ...
- 简明易懂,将细节隐藏,面向新手树立web开发概念——学完Java基础语法,超快速上手springboot+mybatiJavaWeb开发
简明易懂,将细节隐藏,面向新手树立web开发概念 --学完Java基础语法,超快速上手JavaWeb开发 Web本质(先忽视各种协议) Web应用可以理解为浏览器和服务器之间的交互. 我们可以看一个简 ...
- Asp.Net Web API开发微信后台
如果说用Asp.Net开发微信后台是非主流,那么Asp.Net Web API的微信后台绝对是不走寻常路. 需要说明的是,本人认为Asp.Net Web API在开发很多不同的请求方法的Restful ...
- C++后台实践:古老的CGI与Web开发
本文写给C/C++程序猿,也适合其他对历史感兴趣的程序猿 ============================================= 谈到web开发,大家首先想到的PHP.JavaEE ...
- 渐进式web应用开发-- 使用后台同步保证离线功能(六)
_ 阅读目录 一:什么是后台同步保证离线功能呢? 二:后台同步是如何实现的呢? 三:如何给sync事件传递数据? 四:在我们的项目中添加后台同步功能 回到顶部 一:什么是后台同步保证离线功能呢? 在我 ...
- 使用ztree展示树形菜单结构
官网:http://www.treejs.cn/v3/main.php#_zTreeInfo 一.功能简介 在权限系统中,实现给角色指定菜单权限的功能.主要包括以下几点: 读取全部菜单项,并以树形结构 ...
- java web 开发三剑客 -------电子书
Internet,人们通常称为因特网,是当今世界上覆盖面最大和应用最广泛的网络.根据英语构词法,Internet是Inter + net,Inter-作为前缀在英语中表示“在一起,交互”,由此可知In ...
随机推荐
- HttpContext的dynamic包装器DynamicHttpContext (附原代码)
项目背景:在.net framework下使用asp.net webform,特别是aspx+ajax+ashx中,ashx后台代码获取传入参数的时候,需要很多[“…”],我用dynamic对他进行包 ...
- Docker简明教程
Docker简明教程 [编者的话]使用Docker来写代码更高效并能有效提升自己的技能.Docker能打包你的开发环境,消除包的依赖冲突,并通过集装箱式的应用来减少开发时间和学习时间. Docker作 ...
- Silverlight behavior(行为) trigger 大全
behavior是超级有用的东西,一定要学会,因为这个就是面向对象编程中的封装.超级重要! 欢迎大家如果有好的效果,可以给我留言,我打算不断的整理这个behavior,希望不久用behavior可以做 ...
- const,static,extern简介
一.const与宏的区别: const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量. 编译时刻:宏是预编译(编译之前处理),const是编译阶段. 编 ...
- Settings
任何一个构件都有唯一的坐标,根据这个坐标可以定义其在仓库中的唯一存储路径,这是Maven的仓库布局方式. groupId/artifactId/version/artifactId-version(- ...
- unity文件解析以及版本控制
刚开始使用unity做开发时,拿到一个范例工程先上传SVN,之后再自己做一些修改后,发现有非常多文件都有变化,这才知道有很多本地生成的文件,是不用上传的,但是不知道哪些才是需要共用的.之后又困扰于修改 ...
- EasyUI 开发笔记(一)
由于某些原因,在公司做的后台需要改成类似于Ext.js 形式的后台,主要看好其中的 框架布局,以及tab开页面和弹出式内部窗体. 后来看看,改成EasyUI,较Ext.js 库小很多,也便于公司的初级 ...
- Redis中struct运用
c#操作缓存例如redis比较推荐ServiceStack 在redis中运用key-value存储数据,但是遇到结构体该如何处理,是类可通过get<type>(key)获得,那struc ...
- C# js jquery复制textbox内容总结
C# Language//复制: private void button1_Click(object sender, System.EventArgs e) { if(textBox1.Selec ...
- CentOS7下安装MySQL5.7安装与配置(转)
原文地址:http://www.centoscn.com/mysql/2016/0626/7537.html 安装环境:CentOS7 64位 MINI版,安装MySQL5.7 1.配置YUM源 在M ...