EasyUI的后台界面

摘要:
EasyUI后台界面构建和极端重建〇。序言应该理解事物的样子,至少让我们看到它,然后我们才能提出有针对性的观点。因此,为了有话可说,而不仅仅是聊天,让我们从UI开始。我们将使用easyui框架,它在后台管理页面UI中广泛使用。过去,当使用easyui时,每一页都必须从0开始,或者通过“复制和粘贴”方法费力地修改前一页。一个长页面会导致页面太大,难以维护。
EasyUI的后台界面搭建及极致重构 〇、前言

要了解一个东西长什么样,至少得让我们能看到,才能提出针对性的见解。所以,为了言之有物,而不是凭空漫谈,我们先从UI说起,后台管理页面的UI我们将使用应用比较普遍的easyui框架。

以前在用easyui的时候,每个页面都得从0做起,或者不厌其烦地由以前的页面通过“复制-粘贴”的方式来修改,久页久之,就会造成页面庞大且难以维护。其实,前端的html,javascript代码与后端的代码是一样的,通过一定的组织,把重复的代码抽离出来,同样也通过达到很好的复用率。而MVC的天生的Layout布局与分布视图(Partial View),就是对重复代码抽离的需求有很好的支持。

一、目录 二、EasyUI-Layout布局

_Layout.cshtml

MVC的布局,最先当然是作为根视图存在的_Layout.cshtml了,_Layout.cshtml很简单,只是负责一些样式文件和公共脚本的引用。开发阶段,先使用绝对地址进行引用,发布的时候再进行压缩代码的考虑。

在_Layout.cshtml中,除了必需的@RenderBody() ,还定义了两个Section,分别为负责引用子级视图样式的@RenderSection("header", false) 和负责引用子级视图脚本的@RenderSection("footer", false)

复制代码
 1 @{
 2     Layout = null;
 3 }
 4 <!DOCTYPE html>
 5 <html>
 6 <head>
 7     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 8     <meta name="viewport" content="width=device-width, initial-scale=1.0">
 9     <title>@ViewBag.Title - OSharp管理系统</title>
10     <link href="http://t.zoukankan.com/Content/themes/gray/easyui.css" rel="stylesheet" />
11     <link href="http://t.zoukankan.com/Content/themes/icon.css" rel="stylesheet" />
12     <link href="http://t.zoukankan.com/Content/osharp-icons.css" rel="stylesheet" />
13     <link href="http://t.zoukankan.com/Content/osharp-admin.css" rel="stylesheet"/>
14     @RenderSection("header", false)
15 </head>
16 <body>
17     @RenderBody()
18     <script src="http://t.zoukankan.com/Scripts/jquery-1.11.1.js" type="text/javascript"></script>
19     <script src="http://t.zoukankan.com/Scripts/jquery.easyui-1.4.1.js" type="text/javascript"></script>
20     <script src="http://t.zoukankan.com/Scripts/locale/easyui-lang-zh_CN.js" type="text/javascript"></script>
21     <script src="http://t.zoukankan.com/Scripts/json2.js" type="text/javascript"></script>
22     <script src="http://t.zoukankan.com/Scripts/osharp.global.js" type="text/javascript"></script>
23     <script src="http://t.zoukankan.com/Scripts/osharp.easyui.js" type="text/javascript"></script>
24     <script src="http://t.zoukankan.com/Scripts/osharp.data.js" type="text/javascript"></script>
25     @RenderSection("footer", false)
26 </body>
27 </html>
复制代码

后台的EasyUI-Layout布局

一般来说,后台管理页面都是这样一个布局方式:

  1. 上边一个顶栏
  2. 左边一个手风琴或树形的导航栏
  3. 中间是一个由iframe加载具体内容页的多选项卡tab页面

这样,就要用到easyui的easyui-layout来做整体布局,左边的导航栏使用easyui-accordion,右边加载内容页的多选项卡使用easyui-tabs。easyui的布局在网上也很普遍,具体的就不说了,完整代码如下:

EasyUI的后台界面第3张View Code

效果如下:

EasyUI的后台界面第4张

左导航数据加载

由上面的代码可知,左边导航菜单,完全是由JS解析后端返回的JSON数据来构建,使用后端来返回数据,而不是在前端构建菜单数据,主要是便于将来进行权限控制,后端可以根据当前用户的权限返回特定的菜单数据。后端代码如下:

EasyUI的后台界面第5张View Code

上面的代码中,添加了一个 [AjaxOnly],作用标记此方法只允许AJAX的调用方式,拦截非Ajax调用,在数据安全上能起到一定的作用。

复制代码
 1 /// <summary>
 2 /// 限制当前功能只允许以Ajax的方式来访问
 3 /// </summary>
 4 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
 5 public class AjaxOnlyAttribute : ActionFilterAttribute
 6 {
 7     /// <summary>
 8     /// Called before an action method executes.
 9     /// </summary>
10     /// <param name="filterContext">The filter context.</param>
11     public override void OnActionExecuting(ActionExecutingContext filterContext)
12     {
13         if (!filterContext.HttpContext.Request.IsAjaxRequest())
14         {
15             filterContext.Result = new ContentResult
16             {
17                 Content = Resources.Mvc_ActionAttribute_AjaxOnlyMessage
18             };
19         }
20     }
21 }
复制代码

打上此自定义属性后,如果使用非AJAX的方式来调用上面的GetNavData代码,无法得到返回的JSON数据

EasyUI的后台界面第8张

正确解析返回数据后,构建导航菜单,点击菜单后打开相应的选项卡

EasyUI的后台界面第9张

三、EasyUI-datagrid布局

提取父视图(模板)_DataGridLayout.cshtml

在实践中,我们会发现,大部分 datagrid 的代码组织方式都相似的,不同的只是数据源不同,操作之后提交的URL不同。为了减少重复代码,提高代码的复用率,我们可以把共同的代码提取出来,而MVC的 Layout 又刚好是支持嵌套的,那么,类似于前面的 _Layout.cshtml,我们可以提取一个datagrid的共同父视图 _DataGridLayout.cshtml。

_DataGridLayout.cshtml 的提取原理如下:

  1. javascript 的变量均是全局变量,并且是有前后顺序的,就可以按需要进行重新赋值
  2. 在 父视图(_Layout)中初始化 javascript变量,并在适当的位置(变量真正使用之前)向 子视图(Partial View)开放RenderSection
  3. 子视图(Partial View)按需要对 父视图(_Layout)中定义的 javascript变量 进行重新赋值
  4. 正在的运算逻辑运算的时候,使用的就是重新赋值的新值了,以达到复用 Layout 的目的
  5. 父视图中需要的 C# 变量,通过在子视图中定义 ViewBag 传递过去,比如dom元素的id,数据操作的URL等等

根据 easyui-datagrid 的常用变量及上面的原理,定义的_DataGridLayout.cshtml 大致结构如下,请结合注释进行理解:

复制代码
 1 @{
 2     Layout = "~/Areas/Admin/Views/Shared/_Layout.cshtml";
 3     string toolbarItem = ViewBag.ToolbarItem ?? "add,edit,save,cancel,delete";
 4 }
 5 @section header
 6 {
 7 <style type="text/css">
 8     html { font-family: sans-serif; }
 9     .datagrid-header-inner { font-weight: bold; }
10 </style>
11 }
12 @section footer
13 {
14     @*这里进行变量初始化*@
15     <script type="text/javascript">
16         //定义及初始化变量
17         var rownumbers = true, singleSelect = false, ctrlSelect = true, multiSort = false, pageSize = 25;
18         var grid, frozenColumns = [[]], columns = [[]], ...
19 
20         //前置逻辑,将在构造datagrid之前执行
21         var startfunction = function() { };
22         //后置逻辑,将在构造datagrid之后执行
23         var endfunction = function() { }; 
24 
25     </script>
26 
27     @*开放一个Section,让子视图(Partial View)可以插入代码,对上面定义的变量进行重新赋值。*@
28     @RenderSection("customScript", true)
29 
30     @*这里才正在执行业务逻辑*@
31     <script type="text/javascript">
32         $(function () {
33             //执行前置逻辑
34             startfunction();
35 
36             //构造 datagrid
37             grid = $("#grid-@ViewBag.GridId").datagrid({
38                 title: "@ViewBag.Title",
39                 fit: true,
40                 frozenColumns: frozenColumns,
41                 columns: columns,
42                 fitColumns: false,
43                 url: "@ViewBag.GridDataUrl",
44                 ...
45             });
46             
47             //执行后置逻辑
48             endfunction();
49         });
50     </script>
51 }
52 @* 后台还有可能有需要执行的逻辑,开放一个Section *@
53 @RenderSection("endScript", false)
54 }
55 @* datagrid 前面有可能需要插入html,开放一个Section *@
56 @RenderSection("headHtml", false)
57 <div id="grid-@ViewBag.GridId"></div>
58 @* datagrid 后面有可能需要插入html,开放一个Section *@
59 @RenderSection("footHtml", false)
复制代码

结合实际需求,OSharp中定义的一个可用的_DataGridLayout.cshtml 如下,可以根据需求进行更改:

EasyUI的后台界面第12张View Code

实例应用

OSharp.Web组件中,定义了一个专用于返回表格数据的类,表格只需要行数据与总行数

复制代码
 1 /// <summary>
 2 /// 列表数据,封装列表的行数据与总记录数
 3 /// </summary>
 4 /// <typeparam name="T"></typeparam>
 5 public class GridData<T>
 6 {
 7     public GridData()
 8         : this(new List<T>(), 0)
 9     { }
10 
11     public GridData(IEnumerable<T> rows, int total)
12     {
13         Rows = rows;
14         Total = total;
15     }
16 
17     /// <summary>
18     /// 获取或设置 行数据
19     /// </summary>
20     public IEnumerable<T> Rows { get; set; }
21 
22     /// <summary>
23     /// 获取或设置 数据行数
24     /// </summary>
25     public int Total { get; set; }
26 }
复制代码

通过这个类,就可以向easyui返回数据了,如下:

复制代码
 1 [AjaxOnly]
 2 public ActionResult GridData()
 3 {
 4     List<object>data =new List<object>();
 5     for (int i = 1; i <= 20; i++)
 6     {
 7         var item = new { Id = i, Name = "UserName" + i, NickName = "用户" + i, IsDeleted = false, CreatedTime = DateTime.Now.AddMinutes(i) };
 8         data.Add(item);
 9     }
10     return Json(new GridData<object>(data, data.Count), JsonRequestBehavior.AllowGet);
11 }
复制代码

有了前面定义的 datagrid 父视图_DataGridLayout.cshtml,用户列表(ViewsUsersIndex.cshtml)的代码就是如此的简单,仅仅需要把columns重新赋值而已

复制代码
 1 @{
 2     ViewBag.Title = "用户信息列表";
 3     Layout = "~/Areas/Admin/Views/Shared/_DataGridLayout.cshtml";
 4 
 5     ViewBag.GridId = "users";
 6     ViewBag.GridDataUrl = Url.Action("GridData");
 7 }
 8 @section customScript
 9 {
10 <script type="text/javascript">
11     columns = [[
12         { field: "Id", title: "编号",  40, halign: "center", align: "right", sortable: true },
13         { field: "Name", title: "用户名",  150, sortable: true },
14         { field: "NickName", title: "用户昵称",  150, sortable: true },
15         { field: "IsDeleted", title: "已删除",  80, sortable: true, align: "center", formatter: formatBoolean },
16         { field: "CreatedTime", title: "创建时间",  150, halign: "center", align: "center", sortable: true, formatter: function (value) { return $.osharp.tools.formatDate(value); } }
17     ]];
18 </script>
19 }
复制代码

这样,便可以运行出用户列表的结果,如下

EasyUI的后台界面第19张

比如添加一个角色信息列表,视图(ViewsRolesIndex.cshtml)也同用户列表一样,简单到极致:

复制代码
 1 @{
 2     ViewBag.Title = "角色信息列表";
 3     Layout = "~/Areas/Admin/Views/Shared/_DataGridLayout.cshtml";
 4 
 5     ViewBag.GridId = "roles";
 6     ViewBag.GridDataUrl = Url.Action("GridData");
 7 }
 8 @section customScript
 9 {
10     <script type="text/javascript">
11         columns = [[
12             { field: "Id", title: "编号",  40, halign: "center", align: "right", sortable: true },
13             { field: "Name", title: "角色名",  150, sortable: true },
14             { field: "Remark", title: "角色描述",  150, sortable: true },
15             { field: "CreatedTime", title: "创建时间",  150, halign: "center", align: "center", sortable: true, formatter: function (value) { return $.osharp.tools.formatDate(value); } }
16         ]];
17     </script>
18 }
复制代码

运行效果:

EasyUI的后台界面第22张

就是这样,多动脑,多总结,前端的代码也同样能像后台C#代码一样重构,重构到极致。

未完待续。。。

四、开源说明

 (一)github.com

OSharp项目已在github.com上开源,地址为:https://github.com/i66soft/osharp,欢迎阅读代码,欢迎 Fork,如果您认同 OSharp 项目的思想,欢迎参与 OSharp 项目的开发。

  在Visual Studio 2013中,可直接获取 OSharp 的最新源代码,获取方式如下,地址为:https://github.com/i66soft/osharp.git

EasyUI的后台界面第23张

 (二)nuget

OSharp的相关类库已经发布到nuget上,欢迎试用,直接在nuget上搜索 “osharp” 关键字即可找到
EasyUI的后台界面第24张

列导航
    1. 【开源】OSharp框架解说系列(1):总体设计
    2. 【开源】OSharp框架解说系列(2):从后台UI说起-EasyUI的后台界面搭建
    3. 【开源】OSharp框架解说系列(2.2):EasyUI复杂布局及数据操作

免责声明:文章转载自《EasyUI的后台界面》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Ubuntu 18.04 配置ThinkPHP 6.0 管道模式与中间件的实现分析下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

在线浏览PDF文件的实用jquery插件推荐(转)

在web开发当中我们经常需要进行需要在线浏览PDf内容,在线嵌入动态pdf,传统的解决方法安装客户端PDF阅读器,如果是在谷歌是可以在线浏览的,因为他自身就带了一些插件,以前遇到这样的问题往往是费时又费力,很不好解决, 今天就给大家分享一系列使用javascript实现的pdf插件效果,无需借助第三方插件就可以实现在线浏览功能,非常实用 jQuery...

Javascript 刷新框架及页面的方法总集

项目中会用到很多关于框架页面刷新的方法。先来看一个简单的例子:下面以三个页面分别命名为frame.html、top.html、bottom.html为例来具体说明如何做。frame.html 由上(top.html)下(bottom.html)两个页面组成,代码如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4...

【译】Js基础运行机制

一、js的工作原理:引擎、运行时与调用栈概述 JavaScript引擎的一个流行示例是Google的V8引擎。比如,V8引擎用于Chrome和Node.js。 该引擎包括两个主要组件:*内存堆-这是内存分配的地方*调用堆栈-这是代码执行时堆栈帧的位置 运行时浏览器中有几乎所有JavaScript开发人员都在使用的API(例如“ setTimeout”)。...

EasyUI DataGrid 动态新增 Toolbar

easyui datagrid 是一个弹性蛮大的元件,但是官方文件有点不足,是比较可惜的一点。下面,一条小龙会介绍一下,如何动态新增 toolbar button。这个技巧读者可以举一反三应用在任何想动态新增的部分上。这边尽量简化好来介绍其中的关键点。 一般写 JavaScript 应用的程式,实务上一条小龙自己开发时都会希望能尽量把商业逻辑放在serve...

css图片+文字浮动(文字包围效果)

css图片+文字浮动(文字包围效果): 在网页中,我们有时想实现这个效果,但是 <div id="test"> <img src="gdimages/01.jpg" alt=""/>《Web前端设计与开发-HTML+CSS+JavaScript+HTML 5+jQuery》是QST青软实训推出的“在实践中成长”系列丛书之...

【cocos2d-js官方文档】二十四、如何在android平台上使用js直接调用Java方法

在cocos2d-js 3.0beta中加入了一个新特性,在android平台上我们可以通过反射直接在js中调用java的静态方法。它的使用方法很简单: var o = jsb.reflection.callStaticMethod(className, methodName, methodSignature, parameters...) 在callS...