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 ...
随机推荐
- 谈谈自己对C语言中函数指针的一些理解 (第一次写博客,有点小兴奋哈)
1.函数指针声明的格式及简单的使用 (1)格式:(返回值)(*函数指针名)(参数列表) 例如:声明一个无参数无返回值的函数指针(void)(*p)(void). (2)将函数指针指向某个无参数无 ...
- TransactionScope 使用记录
最近使用TransactionScope来进行处理不同数据库的操作问题,当看到这里的时候肯都是在使用或者要使用的吧,关于他的使用网络上一大堆,我在使用的时候遇到了一下的问题,作为记录,可能会对以后使用 ...
- meteor报错之:MongoDB had an unspecified uncaught exception.
今天测试的时候meteor报了个错 如下: MongoDB had an unspecified uncaught exception. This can be caused by MongoDB b ...
- C#方法参数传递机制
1:value(值传递).ref(引用传递).out(输出传递) ref和out使用效果上面是等效的,它们的区别在于:参数标记为ref,那么必须在调用函数之前初始化参数的值:参数标记为out,调用函数 ...
- ubuntu环境下使用apt-get配置apache+php+mysql
主要步骤:1,安装apachesudo apt-get install apache2sudo /etc/init.d/apache2 restart2,安装phpsudo apt-get insta ...
- poj1741 (点分治)
Problem Tree 题目大意 给一棵树,有边权.求树上距离小于等于K的点对有多少. 解题分析 点分治.对每一棵子树进行dfs,求出每棵子树的重心,继而转化为子问题. 对于经过根的路径i--j,令 ...
- 2014嘉杰信息杯ACM/ICPC湖南程序设计邀请赛暨第六届湘潭市程序设计竞赛
比赛链接: http://202.197.224.59/OnlineJudge2/index.php/Contest/problems/contest_id/36 题目来源: 2014嘉杰信息杯ACM ...
- Deactivate .NET refector
8.5版本用注册机注册时手快成Standed版本,搞错......,能否Deactivated,发现要联网..... 接下来查找.net reflector 在位置%UserProfile%\AppD ...
- Hive自定义函数的学习笔记(1)
前言: hive本身提供了丰富的函数集, 有普通函数(求平方sqrt), 聚合函数(求和sum), 以及表生成函数(explode, json_tuple)等等. 但不是所有的业务需求都能涉及和覆盖到 ...
- 【转】构建C1000K的服务器(1) – 基础
原文来自 ideawu 构建C1000K的服务器(1) – 基础 著名的 C10K 问题提出的时候, 正是 2001 年, 到如今 12 年后的 2013 年, C10K 已经不是问题了, 任何一个普 ...