基于MVC4+EasyUI的Web开发框架经验总结(3)- 使用Json实体类构建菜单数据

最近花了不少时间在重构和进一步提炼我的Web开发框架上,力求在用户体验和界面设计方面,和Winform开发框架保持一致,而在Web上,我主要采用EasyUI的前端界面处理技术,走MVC的技术路线,在重构完善过程中,很多细节花费不少时间进行研究和提炼,一步步走过来,也积累了不少经验,本系列将主要介绍我在进一步完善我的Web框架基础上积累的经验进行分享,本随笔主要介绍使用如何使用Json实体类构建菜单数据,然后在主界面中进行使用。

菜单的界面效果如下所示,菜单分为一级菜单、二级菜单、三级菜单,他们各自在位置上是不同的定义,这个界面布局规定三级菜单就是最小的菜单节点了,也就是叶子节点。

要实现以上的菜单,需要把菜单定义成相关的Json数据,然后通过脚本把它们添加到界面里面去,如下数据和脚本就是定义相关的菜单数据的。

    <script type="text/javascript">
var _menus = {
"default": [
{
"menuid": "1", "icon": "icon-computer", "menuname": "权限管理",
"menus": [
{ "menuid": "13", "menuname": "用户管理", "icon": "icon-user", "url": "/User/Index" },
{ "menuid": "14", "menuname": "组织机构管理", "icon": "icon-organ", "url": "/OU/Index" },
{ "menuid": "15", "menuname": "角色管理", "icon": "icon-group-key", "url": "/Role/Index" },
{ "menuid": "16", "menuname": "功能管理", "icon": "icon-key", "url": "/Function/Index" },
{ "menuid": "17", "menuname": "登陆日志", "icon": "icon-view", "url": "/LoginLog/Index" }
]
},
{
"menuid": "2", "icon": "icon-user", "menuname": "其他管理",
"menus": [{ "menuid": "21", "menuname": "修改密码", "icon": "icon-lock", "url": "javascript:ShowPasswordDialog()" }
]
}
],
"point": [
{
"menuid": "3", "icon": "icon-computer", "menuname": "事务中心",
"menus": [
{ "menuid": "33", "menuname": "测试菜单1", "icon": "icon-user", "url": "../Commonpage/building.htm" },
{ "menuid": "34", "menuname": "测试菜单2", "icon": "icon-organ", "url": "../Commonpage/building.htm" },
{ "menuid": "35", "menuname": "测试菜单3", "icon": "icon-group-key", "url": "../Commonpage/building.htm" },
{ "menuid": "36", "menuname": "测试菜单4", "icon": "icon-key", "url": "../Commonpage/building.htm" }
]
},
{
"menuid": "4", "icon": "icon-user", "menuname": "其他菜单",
"menus": [{ "menuid": "41", "menuname": "测试菜单5", "icon": "icon-lock", "url": "../Commonpage/building.htm" }]
}
]
}; function showSubMenu(url, title, menuCategory, defaultIcon) {
if (defaultIcon == null || defaultIcon == "") {
defaultIcon = "icon-table";
}
addTab(title, url, "icon " + defaultIcon);
Clearnav();
if (menuCategory != "") {
addNav(_menus[menuCategory]);
}
}
</script>

从上面的菜单Json数据来看,它是一个字典的Json数据列表,在Web界面上,通过下面的代码可以展开上面Json定义的二级菜单。

<li><a href="#" onclick="showSubMenu('/User/Index', '用户管理', 'default')">权限管理</a></li>

虽然上面的定义的数据能够解决菜单的显示问题,但是对于我们需要动态控制的菜单,显然做不到,因此需要把上面的json数据,通过菜单控制器进行动态生成才可以,然后在脚本里面通过Jquery的方式获取Json数据,如下所示。

        var _menus = {};
//同步获取
$.ajax({
type: 'GET',
url: '/Menu/GetMenuData?r=' + Math.random(),
async: false,//同步
dataType: 'json',
success: function (json) {
_menus = json;
},
error: function (xhr, status, error) {
alert("操作失败"); //xhr.responseText
}
});

上面的GetMenuData方法,通过后台的控制器进行动态生成的,它的代码如下所示

        /// <summary>
/// 获取树形展示数据
/// </summary>
/// <returns></returns>
public ActionResult GetMenuData()
{
string json = GetTreeJson("-1", "", "");
json = json.Trim(',');
return Content(string.Format("[{0}]", json));
} /// <summary>
/// 递归获取树形信息
/// </summary>
/// <returns></returns>
private string GetTreeJson(string PID, string folderIcon, string leafIcon)
{
string condition = string.Format("PID='{0}' ", PID);
List<MenuInfo> nodeList = BLLFactory<Menu>.Instance.Find(condition);
StringBuilder content = new StringBuilder();
foreach (MenuInfo model in nodeList)
{
string ParentID = (model.PID == "-1" ? "0" : model.PID);
string subMenu = this.GetTreeJson(model.ID, folderIcon, leafIcon);
string parentMenu = string.Format("{{ \"id\":\"{0}\", \"pId\":\"{1}\", \"name\":\"{2}\" ", model.ID, ParentID, model.Name);
if (string.IsNullOrEmpty(subMenu))
{
if (!string.IsNullOrEmpty(leafIcon))
{
parentMenu += string.Format(",\"icon\":\"{0}\" }},", leafIcon);
}
else
{
parentMenu += "},";
}
}
else
{
if (!string.IsNullOrEmpty(folderIcon))
{
parentMenu += string.Format(",\"icon\":\"{0}\" }},", folderIcon);
}
else
{
parentMenu += "},";
}
} content.AppendLine(parentMenu.Trim());
content.AppendLine(subMenu.Trim());
}
return content.ToString().Trim();
}

不过对于上面的代码,我觉得虽然能解决问题,能够正确生成相关的Json代码,但是感觉不够优雅,我不喜欢使用拼凑方法构建数据。

前面看了Menu的Json脚本,我说过他是一个字典类型的Json数据格式,那么我们是否可以通过字典和实体信息来承载,然后直接通过ToJson方法出来呢?答案是可以的。

        /// <summary>
/// 获取菜单的树形展示数据
/// </summary>
/// <returns></returns>
public ActionResult GetMenuData()
{
Dictionary<string, List<MenuData>> dict = new Dictionary<string, List<MenuData>>(); List<MenuInfo> list = BLLFactory<Menu>.Instance.GetTopMenu(MyConstants.SystemType);
int i = 0;
foreach (MenuInfo info in list)
{
if (!HasFunction(info.FunctionId))
{
continue;
}
List<MenuData> treeList = new List<MenuData>();
List<MenuNodeInfo> nodeList = BLLFactory<Menu>.Instance.GetTreeByID(info.ID);
foreach (MenuNodeInfo nodeInfo in nodeList)
{
if (!HasFunction(nodeInfo.FunctionId))
{
continue;
}
MenuData menuData = new MenuData(nodeInfo.ID, nodeInfo.Name, string.IsNullOrEmpty(nodeInfo.WebIcon) ? "icon-computer" : nodeInfo.WebIcon);
foreach (MenuNodeInfo subNodeInfo in nodeInfo.Children)
{
if (!HasFunction(subNodeInfo.FunctionId))
{
continue;
}
string icon = string.IsNullOrEmpty(subNodeInfo.WebIcon) ? "icon-organ" : subNodeInfo.WebIcon;
menuData.menus.Add(new MenuData(subNodeInfo.ID, subNodeInfo.Name, icon, subNodeInfo.Url));
}
treeList.Add(menuData);
} //添加到字典里面,如果是第一个,默认用default名称
string dictName = (i++ == 0) ? "default" : info.ID;
dict.Add(dictName, treeList);
} string content = ToJson(dict);
return Content(content.Trim(','));
}

上面的代码,通过MenuData的对象数据,来承载相关的菜单信息,然后把它添加到字典Dictionary<string, List<MenuData>> dict 里面就可以了,这样的代码,没有那么多拼凑出来的感觉,是不是很好看呢?把对象转换为Json数据,直接通过ToJson就可以解决了,很简单吧。

而菜单的权限控制,就是通过集合权限管理进行判断,父菜单如果没有权限,就直接跳过,不在继续生成下面的子菜单,权限判断的如下所示。

if (!HasFunction(info.FunctionId))
{
continue;
}

当然,在界面上展开二级菜单的操作界面,也应该通过脚本动态进行生成的,这样才能做到所有的内容动态构建。

        <ul class="navigation" style="display:block">
@Html.Raw(@ViewBag.HeaderScript)</ul>

上面使用ViewBag对象进行传递脚本内容到界面上,其实后台生成的操作,是一行HTML代码就是了,代码类似下面的内容。

<li><a href="#" onclick="showSubMenu('/User/Index', '用户管理', 'default')">权限管理</a></li>

最后出来的效果,就是博客开始介绍的界面截图,没有任何变化,但是代码我们已经经过了几步的优化整理,看起来很清爽,更能实现动态变化了。

有空可以回顾下其他两篇的经验总结内容:

基于MVC4+EasyUI的Web开发框架经验总结(1)-利用jQuery Tags Input 插件显示选择记录

基于MVC4+EasyUI的Web开发框架经验总结(2)- 使用EasyUI的树控件构建Web界面

使用Json实体类构建菜单数据的更多相关文章

  1. 基于MVC4+EasyUI的Web开发框架经验总结(3)- 使用Json实体类构建菜单数据

    最近花了不少时间在重构和进一步提炼我的Web开发框架上,力求在用户体验和界面设计方面,和Winform开发框架保持一致,而在Web上,我主要采用EasyUI的前端界面处理技术,走MVC的技术路线,在重 ...

  2. (转)基于MVC4+EasyUI的Web开发框架经验总结(3)- 使用Json实体类构建菜单数据

    http://www.cnblogs.com/wuhuacong/p/3669708.html 最近花了不少时间在重构和进一步提炼我的Web开发框架上,力求在用户体验和界面设计方面,和Winform开 ...

  3. Python中xml、字典、json、类四种数据的转换

    最近学python,觉得python很强很大很强大,写一个学习随笔,当作留念注:xml.字典.json.类四种数据的转换,从左到右依次转换,即xml要转换为类时,先将xml转换为字典,再将字典转换为j ...

  4. Mybatis中实体类属性和数据列之间映射的四种办法

    http://blog.csdn.net/lmy86263/article/details/53150091 Mybatis不像hibernate中那么自动化,通过@Column注解或者直接使用实体类 ...

  5. .NET平台开源项目速览(18)C#平台JSON实体类生成器JSON C# Class Generator

    去年,我在一篇文章用原始方法解析复杂字符串,json一定要用JsonMapper么?中介绍了简单的JSON解析的问题,那种方法在当时的环境是非常方便的,因为不需要生成实体类,结构很容易解析.但随着业务 ...

  6. JSon实体类快速生成插件 GsonFormat 1.2.0

    写在前头:本插件只适用 android studio和 Intellij IDEA 工具,eclipse 的少年无视我吧!!! 这是一个根据JSONObject格式的字符串,自动生成实体类参数. gi ...

  7. C#:实体类中做数据验证

    主要是在实体类中验证 using System; namespace Jone.Function.attribute{        /// <summary>        /// 附加 ...

  8. 快速生成json实体类

    读取一个json文件,并与实体相对应: static void Main(string[] args) { string json = ""; FileStream fs = ne ...

  9. .net webapi 收不到json 实体类参数,返回的json中带有k__BackingField

    案例:实体类是从WCF项目中复制到webapi项目中,去掉了[DataContract],[DataMember],但[Serializable] 没去掉. 在ApiController 中,实体类输 ...

随机推荐

  1. [2013山东ACM]省赛 The number of steps (可能DP,数学期望)

    The number of steps nid=24#time" style="padding-bottom:0px; margin:0px; padding-left:0px; ...

  2. 自己写CPU第五级(5)——测试逻辑、实现移动和空指令

    我们会继续上传新书<自己写CPU>(未公布),今天是19片,我每星期试试4 5.6 測试程序1--測试逻辑操作实现效果 编写例如以下測试程序用于检验逻辑操作指令是否实现正确,文件名称命名为 ...

  3. android static达到Service与Activity于Handler沟通

    供static理解力,仅适用于static理解力,不喜勿喷 第一种方式:离Service中获取Activity的static变量,调用该静态变量的getHandler()获取Handler进行发送消息 ...

  4. OCP读书笔记(27) - 题库(ExamG)

    601.You need to perform a block media recovery on the tools01.dbf data file in the SALES database by ...

  5. 采用oracle官方文件(11G)——初步Concept

    采用oracle官方文件(11G)示例 这里是oracle官方文档界面,想了解oracle,阅读官方文档是唯一的方法,大致了解官方文档的使用,对官方文档有一个更直观的认识.文档可通过文章关联的链接查看 ...

  6. hdu Lowest Bit

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1196 大水题   lowbit   的应用    (可以取出一个数二进制中的最后一个1.树状数组常用, ...

  7. crawler_解析之_jquery_语法选择器使用方法

    爬虫解析一般使用 正则或者给予样式的 jquery语法选择器 正则是根本,类比jsoup基于dom,底层也有部分是基于正则实现的,linux操作系统 文本处理也是借助强大的正则体现的 .关于正则 请参 ...

  8. linux_windows下配置tomcat区别 ,不同子域名映射不同 项目

    windows下 均为修改tomcat/bin/server.xml 在最后 替换 注意 docBase / <Realm className="org.apache.catalina ...

  9. 【机器学习算法-python实现】KNN-k近邻算法的实现(附源代码)

    ,400],[200,5],[100,77],[40,300]]) shape:显示(行,列)例:shape(group)=(4,2) zeros:列出一个同样格式的空矩阵,例:zeros(group ...

  10. yii 使用 mongodb 小工具 YiiMongoDbSuite

    YiiMongoDbSuite下载链接: http://www.yiiframework.com/extension/yiimongodbsuite/ 如果你的yii和mongodb它已经建立了一个良 ...