礼物一:树型实体的抽象与封装

  所谓树型实体,就是具有树型结构关系的实体,比如省、市、区。对于初学者,可能会创建三张表进行存储,有经验的开发者通过引入ParentId将设计简化为一张表,但是基于ParentId的设计也不够完美,主要问题是查找某个节点的所有上级或所有下级时,都需要进行递归,这是一个低效而复杂的操作。

  更有经验的开发者会引入物化路径Path,物化路径是对节点关系的记录,一般格式为:当前节点Path = 父节点Path + 当前节点Id + “,”,注意物化路径的最后一定是某个符号,一般为逗号。

  一旦物化路径设置完成,查找所有上级和下级就非常简单,查找所有上级只需要从当前节点的Path中,用逗号分隔出Id即可,查找所有下级,通过StartsWith查询Path列,也就是Sql中的Like ‘xxx%’。

  虽然物化路径在查询节点关系方面非常高效,但也不是没有成本的,主要成本在于修改节点关系之后,该节点的所有下级节点的物化路径都需要更新。比如某个节点修改了父节点,那么除了当前节点的Path需要更新外,它的所有下级节点也需要更新,这是一个代价高昂的操作。想像一下,当一个节点下面有数千个,甚至数万个节点,修改一下节点关系将带来多么严重的后果。不过一般树型结构的数据量都不会很大,所以这个问题也不用太多考虑,你只需要了解用这种设计方案有什么弊端即可。

  当使用了EasyUi的TreeGrid这种控件以后,可以在表格上随意编辑和修改,甚至可以通过拖拽的方式修改父节点,仅在最后一刻进行保存,而保存的时候使用工作单元DbContext进行操作,这时候你会发现物化路径的更新将是一个非常棘手的问题。

  树型结构也有规律可循,甚至TreeGrid上的操作都可以进行抽象,我在领域层定义了ITreeEntity、TreeEntityBase、ITreeEntityQuery、TreeEntityQuery等几个类和接口,应用层定义ITreeBatchService、TreeBatchService,表现层定义基控制器TreeGridControllerBase。通过这几个类进行抽象,树型结构的基本操作都内置到框架中,业务类通过继承基类就完成了大部分工作。

  值得一提的是, TreeGridControllerBase提供了一个加载模式LoadMode,默认为异步加载模式,每次只查询一级节点。具体控制器通过重写加载模式,可以切换为同步加载,即一次加载全部节点,另外还提供了一种根节点异步加载模式,即根节点异步加载,下级节点同步加载,通俗的说就是第一次只加载根节点,点击根节点查询出全部子节点。当然,这些功能都不需要你手写代码,全部内置。

  由于本篇只是简介,后续文章再详细介绍。

礼物二:EasyUi TreeGrid抽象与封装

  对于树型实体的编辑操作,一般可以使用Tree控件,再配合一个表单或表格进行,但TreeGrid是更好的选择。

  Easyui treegrid 有很多小bug,比如getChanges方法获取的结果不正确,分页总行数错误等,这些问题都需要自己解决。

  我对treegrid的封装,除了修复一些bug外,另外对树型表格上的操作进行了抽象,将基本操作都内置到框架中。

  大体功能如下:

  1. 表格编辑
  2. 添加根节点
  3. 添加下级节点
  4. 插入同级节点(上方)、
  5. 插入同级节点(下方)
  6. 自动创建连续的排序号(服务端+客户端配合完成)
  7. 上移
  8. 下移
  9. 拖拽排序
  10. 修正排序号
  11. 拖拽修改父节点
  12. 限制可拖拽的层级
  13. 批量修改,一次保存
  14. 冻结节点
  15. 启用节点
  16. 支持不同加载模式
  • 同步加载模式
  • 异步加载模式
  • 根节点异步加载模式

  17. 支持对根节点(第一级节点)分页

  18. 支持查询时显示所有上级节点

  19. 支持右键菜单

  先来几个截图。

  对于表格上的编辑操作,我是用官方提供的edatagrid扩展,复制了一份来改造的,拖拽使用的是官方提供的treegrid.dnd扩展,也简单改了下 。

  关于easyui的性能,如果使用datagrid控件很慢,一般是因为没有设置列宽,这是必须设置的,不然奇慢。Treegrid虽然从datagrid控件派生,但行为上很多不同,datagrid操作行索引index,而treegrid操作的是id。

  我在封装treegrid的时候发现,40个节点左右,treegrid提供的所有操作id的方法都非常慢,断点调试能明显感觉卡一下。由于没有源码,无法调优,所以你在使用我提供的拖拽排序和修正排序号这些功能时,发现性能很差不要惊讶,为何纯客户端操作会如此之慢,那是easyui底层的问题,因为需要调用它的相关方法。

  至于你担心我封装的服务端控件解析可能存在性能问题,一般不需要太紧张,我目前没有考虑性能,一旦服务端控件解析成为性能瓶颈,我会优化它。

  另外一点,由于是一次性保存,可能会批量更新很多节点,对此我没有进行性能优化,使用的是EF的对象一个个的更新,可能会比较慢,不过考虑到这些操作一般是管理员干的,慢一点就让他忍忍好了。

  封装以后,业务代码就非常简单了,控制器代码如下。

  视图还是那么干净,一行js都没有,代码如下。

  可以看到,虽然treegrid与datagrid显著不同,但封装之后,基本没啥区别,大量降低了学习成本(关于过度封装的危害,我后续文章再述)。

礼物三:EasyUi ComboTree控件的抽象与封装

  效果如下图所示。

  调用代码如下。

礼物四: EasyUi ComboBox 控件的抽象与封装

  支持了N级联动,这在省市区这类场景非常有用,使用非常简单,设置父控件的Child方法即可。

  另外支持了值的延迟加载,easyui默认提供的value并不好用,当控件加载完成之前,会在文本框中显示出来,很难看,我提供了一个LazyValue来设置值,仅当控件加载完毕才开始设置值。

礼物五:通用业务模块之字典管理

  字典是业务系统中一个重要的模块,而且也是一个通用模块,我将这个模块开放出来供大家参考和使用。

  由于字典是一个树型结构,所以直接继承树型实体相关基类即可,采用treegrid进行编辑,注意字典控制器重写了加载模式为根节点异步加载,当你点击根节点时,会展示全部下级节点。

  同时,我还提供了一个思维导图供大家参考,我一般采用思维导图来整理需求。这个文件在Document项目中。

  字典管理采用treegrid,这只是进行编辑,那么如何使用它呢?

  我们可以采用combotree控件来展示,如下图所示。

  该如何调用方便呢?可以直接调用combotree控件,然后设置服务端url。

  但这是最简单的调用方式吗?不是,上面的调用需要记住url和其它一些参数,所以还是容易出错,我们再进行一层封装。

  你只需要传递一个code,即字典编码,这才是最简单的调用方式。通过本示例,你会发现封装是分层次的,必须层层封装才能让工作更简单,当你的业务UI组件大量封装以后,不仅整个系统简单优雅,开发难度将显著降低,而且学习成本也大幅下降。

礼物6:通用业务模块之地区管理

  地区管理也是一个重要的通用模块,并且也是基于树型结构,所以这次顺便开放出来。

  封装很简单,主要依赖combox的N级联动和延迟设置值。

  调用代码如下。

  由于EasyUi坑很多,没有一个照应将会走不少弯路,所以特开一个EasyUi专群(157809322),本群仅限EasyUi开发者,以后碰到问题,大家互相帮助。

  下一篇将继续介绍表现层和MVC——MVC的封装和抽象。

  这回下载提供了两个数据库,请下载后还原,就可以看到效果了,无法还原的使用PD导出脚本。

  同志们记得推荐哦,下载地址:

  http://files.cnblogs.com/files/xiadao521/Applications.2015.3.5.1.rar

  http://files.cnblogs.com/files/xiadao521/Framework.2015.3.5.1.rar

  http://files.cnblogs.com/files/xiadao521/Data.2015.3.5.1.rar

  最后,祝各位新年快乐,元宵快乐,吉祥如意。

  .Net应用程序框架交流QQ群: 386092459,欢迎有兴趣的朋友加入讨论。

  .Net Easyui开发交流QQ群(本群仅限Easyui开发者,非Easyui开发者勿进):157809322

  谢谢大家的持续关注,我的博客地址:http://www.cnblogs.com/xiadao521/

版权所有,转载请注明出处 何镇汐的技术博客
 

EasyUi TreeGrid封装的更多相关文章

  1. easyui treegrid 封装(不用分页,用加载更多按钮)延迟加载加加载更多

    /** * @author wsf数据加载 */ ; var intervalId = null; (function (win,$){ $.myCache = { dataCache : {},// ...

  2. 基于EasyUI Treegrid的权限管理资源列表

    1. 前言 最近在开发系统权限管理相关的功能,主要包含用户管理,资源管理,角色管理,组类别管理等小的模块.之前的Web开发中也用过jQueryEasyUI插件,感觉这款插件简单易用,上手很快.以前用到 ...

  3. Jquery easyui treegrid实现树形表格的行拖拽

    前几天修改了系统的一个功能——实现树形列列表的行拖拽,以达到排序的目的.现在基本上功能实现,现做一个简单的总结. 1.拿到这个直接网上搜,有好多,但是看了后都觉得不是太复杂就是些不是特别想看的例子,自 ...

  4. easy-ui treegrid 实现分页 并且添加自定义checkbox

    首先第一点easy-ui  treegrid 对分页没有好的实现, 因为在分页的过程中是按照 根节点来分页的  后台只能先按照 根节点做分页查询  再将子节点关联进去, 这样才能将treegrid 按 ...

  5. easyui treegrid idField 所在属性中值有花括号(如Guid)当有鼠标事件时会报错,行记录一下

    easyui treegrid idField 所在属性中值有花括号(如Guid)当有鼠标事件时会报错,行记录一下

  6. 数据网格和树-EasyUI Datagrid 数据网格、EasyUI Propertygrid 属性网格、EasyUI Tree 树、EasyUI Treegrid 树形网格

    EasyUI Datagrid 数据网格 扩展自 $.fn.panel.defaults.通过 $.fn.datagrid.defaults 重写默认的 defaults. 数据网格(datagrid ...

  7. EasyUI treegrid 加载checked

    EasyUI treegrid  加载checked $(function () { $('#tbDictContTree').treegrid({ title: '数据字典目录管理', iconCl ...

  8. Easyui treegrid 无法显示树形结构解决办法

    easyui treegrid 中检查了数据结构没有问题的,但就是不展示树形结构, 检查发现原来是 var columnsAll = [ { title: '任务ID', field: 'TaskID ...

  9. 适用于zTree 、EasyUI tree、EasyUI treegrid

    #region          System.Text.StringBuilder b_appline = new System.Text.StringBuilder();        Syste ...

随机推荐

  1. paip.jdk1.4 1.5(5.0) 1.6(6.0) 7.0 8.0特点比较与不同

    paip.jdk1.4 1.5(5.0)  1.6(6.0) 7.0   8.0特点比较与不同 作者Attilax ,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地 ...

  2. xml在此生活

    小编尾随学习的步伐.今天小编简要概述xml在此生活,xml她的百度百科这一解释:可扩展标记语言 (ExtensibleMarkup Language, XML).用于标记电子文件使其具有结构性的标记语 ...

  3. Swift编程语言学习1.3——类型安全和投机型

    Swift 是类型安全(type safe )语言.类型安全的语言可以让你清楚地知道代码被处理值类型.假设你需要一个代码String.你绝对不能进去一个不小心传球Int. 因为 Swift 它是类型安 ...

  4. Swift 书面 ToDo App

    下面的代码是使用的全部Xcode Version 6.0.1 (6A317)书面. 因为当使用团队开发stroyboard在并购的诸多不便的时间,所有或使用.xib该文件准备ToDo App. 想要实 ...

  5. 采用curl库

    Windows通过使用curl库: 到http://curl.haxx.se/下了个curl的源代码下来,源代码是用VC6编译的,我在VS2005下又一次进行编译.竟然仅仅有一个警告. cUrl的实现 ...

  6. Android studio 中国的垃圾问题解决

    为了获得良好的刚安装Android studio, 实例importproject时刻,你会发现很多中国的文件夹显示异常.例如下面的附图: 为什么会出现这个问题呢,事实上原因非常easy,由于Andr ...

  7. 讲座:html5于canvas疯狂的炮轰实现

    <html> <head> <title>坎农</title> <script src="../js/jscex.jscexRequir ...

  8. Cocos2d-x源代码解析(1)——地图模块(3)

    接上一章<Cocos2d-x源代码解析(1)--地图模块(2)> 通过前面两章的分析,我们能够知道cocos将tmx的信息结构化到 CCTMXMapInfo.CCTMXTilesetInf ...

  9. 端口扫描之王——nmap入门精讲(转)

    端口扫描在百度百科上的定义是: 端口扫描是指某些别有用心的人发送一组端口扫描消息,试图以此侵入某台计算机,并了解其提供的计算机网络服务类型(这些网络服务均与端口号相关),但是端口扫描不但可以为黑客所利 ...

  10. Android4.4 蓝牙源代码段分析

    最近GOOGLE发布时间Android4.4,我看了看源代码.4.4蓝牙打开过程或这部分的一些变化,判断蓝牙开关是从接口设置settings在里面switch开关,widget当然,它可以切换,也许启 ...