为了让ligerui能更好的工作,我们需要对ligerui的一些常用组件进行封装。首先我们就对最基本的菜单组件进行封装。下面我们先来观察下ligerui中树组件。

       从上面的图片中,我们可以清楚的看到,这就是一棵树。树是一种常用的数据结构,下面引用百度百科的语句:  

树的递归定义:
       树(Tree)是n(n≥0)个结点的有限集T,T为空时称为空树,否则它满足如下两个条件:
       (1)有且仅有一个特定的称为根(Root)的结点;
       (2)其余的结点可分为m(m≥0)个互不相交的子集Tl,T2,…,Tm,其中每个子集本身又是一棵树,并称其为根的子树(Subree)

       下面我们使用接口来描述一颗树。在java中,接口可以很好的描述现实世界中的某种物体具备的行为特点,所以接口非常适合。下面是具体代码:

package net.itaem.ligerui;import java.util.List;/*** liger ui中菜单模型* 这个接口主要用来描述菜单的一些相关操作* @date 2014-08-19 10:17 am* @author 骆宏* @email 846705189@qq.com* * */
public interface ITreeModel {/*** 定义一个字符串,用来表示树模型中的菜单节点* */String MENU = "menu";/*** 定义一个字符串,用来表示数模型中的叶子节点* */String LEAF = "leaf";/*** 返回当前菜单的结构层次* @return 返回菜单的结构层次*         如果是叶子节点,那么返回0* */public int level();/*** 返回当前节点的所有子节点,子节点包括了子菜单以及叶子节点* @return 返回当前菜单的全部子节点* */public List<ITreeModel> children();/*** 返回当前节点的父节点* @return 返回当前节点的父亲节点,如果没有父亲节点,返回null* */public ITreeModel parent();/*** 返回当前节点的节点类型,这里的节点类型一共有两种,一种是菜单,另外一种是叶子节点* @return 节点类型* @see ITreeModel#MENU* @see ITreeModel#LEAF* */public String nodeType();/*** 返回当前节点的url* @return 当前节点的url* */public String url();/*** 放回当前节点的id* @return 当前节点id* */public String id();/*** 返回节点的名字* @return 节点名字* */public String name();/*** 当前节点如果是菜单,那么该菜单默认是否展开呢?如果是返回true,代表展开;否则,代表不展开* @return 返回菜单节点的展开状态* */public boolean isexpand();/*** 设置菜单名字* @param name* */public void setName(String name);/*** 设置菜单url* @param url* */public void setUrl(String url);/*** 设置菜单展开状态* @param isexpend* */public void setIsexpand(boolean isexpand);/*** 设置父节点* @param parent* */public void setParent(ITreeModel parent);/*** 设置孩子节点* @param children* */public void setChildren(List<ITreeModel> children);/*** 设置节点id* @param id* */public void setId(String id);/*** 返回该节点的json数据,包含该节点下面的所有子节点* @return 返回当前节点的json数据* */public String toTreeJson();/*** 返回从根节点到当前节点的所有节点集合,包含当前节点* @return 返回根节点到当前节点的集合* */public List<ITreeModel> route();/*** 返回以当前节点为根节点的一棵子树* @return 返回以当前节点子根节点的子树* */public List<ITreeModel> subTree();
}

在上面我们只是定义了一个树模型。并没有实现代码,为什么这样子做呢?因为每个框架使用的数据格式都不一样,所以我们流出扩展性。如果我们不适用ligerui,而使用dwz,我们的接口类不需要发生变化,只需要添加一个dwz树模型子类即可,ligerui相关组件的代码就无需修改了。 下面使用ligerui实现一个菜单树。具体代码:

package net.itaem.ligerui;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;import net.itaem.vo.MenuVo;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;/*** 这里是liger ui树的插件实现类* @author 骆宏* @date 2014-08-19 19:39 am* @email 846705189@qq.com* */
public class LigerUiTree implements ITreeModel{//定义一个level,用来保存树的层次private int level = 0;//定义一个url,用来保存当前节点的urlprivate String url;//定义一个id,用来保存当前节点idprivate String id;//定义一个isexpend,用来保存节点展开状态private boolean isexpand;//定义一个name,用来保存节点的名称private String name;//定义一个parent,用来保存节点的父亲节点private ITreeModel parent;//定义一个children,用来保存当前节点的所有子节点private List<ITreeModel> children;public LigerUiTree(){}/*** 定义一个基本的构造方法,该构造方法的参数都不能为空* @param id 节点id* @param name 节点name* @param url 节点url* */public LigerUiTree(String id, String name, String url){if(id == null || name == null || url == null) throw new RuntimeException("id name url都不能为空");this.id = id;this.name = name;this.url = url;}public LigerUiTree(String id, String name, String url, ITreeModel parent) {this(id, name, url);this.parent = parent;}public LigerUiTree(String id, String name, String url, List<ITreeModel> children) {this(id, name, url);this.children = children;}@Overridepublic void setUrl(String url) {this.url = url;}@Overridepublic void setId(String id) {this.id = id;}@Overridepublic void setIsexpand(boolean isexpand) {this.isexpand = isexpand;}@Overridepublic void setName(String name) {this.name = name;}public void setParent(ITreeModel parent) {this.parent = parent;}/*** 这里同时会计算树的层次* 并且这里会同时维护parant - children之间的关联管理,也就是在设置当前节点的子节点时,同时会指点这些子节点的父亲节点为当前节点* */public void setChildren(List<ITreeModel> children) {if(children == null) return;   //如果为null,do nothingthis.children = children;//设置level,遍历所有的children树,然后取最大值int max = -1;for(int i=0; i<children.size(); i++){children.get(i).setParent(this);   //维护parent-children的相互关联关系if(children.get(i).level() > max) max = children.get(i).level();}//如果添加的节点都是叶子节点,那么当前层次为2//否则计算最大的树层次 = 子节点最大的层次 + 1if(max != -1 && max != 0){level += max + 1;}else{level = 2;   }}@Overridepublic int level() {//每次要计算树的高度,都必须遍历整棵树的,然后确定树的高度,由于树随时可以被改变,所以这里不适合使用缓存模式return level;}@Overridepublic List<ITreeModel> children() {return children;}@Overridepublic ITreeModel parent() {return parent;}@Overridepublic String nodeType() {if(children != null){   //拥有子节点,则代表该节点是菜单return MENU;}else{return LEAF;}}@Overridepublic String url() {return url;}@Overridepublic String id() {return id;}@Overridepublic boolean isexpand() {return isexpand;}@Overridepublic String name(){return name;}@Overridepublic String toTreeJson() {JSONObject json = new JSONObject();//生成这个节点的基本数据json.put("text", name);json.put("isexpand", isexpand);json.put("url", url);if(parent != null){json.put("pid", parent.id());  }//生成这个节点的子菜单数据JSONArray childrenJson = new JSONArray();if(children != null){for(ITreeModel child: children){//让每个子menu递归的去生成json数据childrenJson.add(toJson(child));}json.put("children", childrenJson);}return json.toString();}/*** 递归入口* @see MenuVo#toJson()* */private String toJson(ITreeModel tree){JSONObject json = new JSONObject();if(tree.children() != null){//生成这个菜单节点的基本数据json.put("text", tree.name());json.put("id", tree.id());if(tree.parent() != null){json.put("pid", tree.parent().id());}json.put("isexpand", tree.isexpand());//生成这个菜单节点的子菜单数据JSONArray childrenJson = new JSONArray();if(tree.children() != null){for(ITreeModel child: tree.children()){//让每个子menu递归的去生成json数据childrenJson.add(toJson(child));}json.put("children", childrenJson);}}else{   //这个节点不是菜单,是菜单下面的一个具体子节点,该节点已经没有子节点了json.put("id", tree.id());if(tree.parent() != null){json.put("pid", tree.parent().id());}json.put("text", tree.name());json.put("url", tree.url());}return json.toString();}@Overridepublic List<ITreeModel> route() {List<ITreeModel> route = new ArrayList<ITreeModel>();ITreeModel current = this;while(current != null){route.add(current);current = current.parent();}java.util.Collections.reverse(route);return route;}@Overridepublic List<ITreeModel> subTree() {List<ITreeModel> subTree = new ArrayList<ITreeModel>();subTree.add(this);if(this.children == null) return subTree;Iterator<ITreeModel> sti = children.iterator();while(sti.hasNext()){ITreeModel tm = sti.next();subTree.add(tm);if(tm.children() != null) subTree.addAll(tm.subTree());}return subTree;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + ((id == null) ? 0 : id.hashCode());result = prime * result + (isexpand ? 1231 : 1237);result = prime * result + level;result = prime * result + (name == null? 0 : name.hashCode());result = prime * result + ((url == null) ? 0 : url.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;LigerUiTree other = (LigerUiTree) obj;if (id == null) {if (other.id() != null)return false;} else if (!id.equals(other.id()))return false;if (isexpand != other.isexpand())return false;if (level != other.level())return false;if(name == null){if(other.name() != null)return false;}if (url == null) {if (other.url() != null)return false;} else if (!url.equals(other.url()))return false;return true;}/*** 返回节点的基本信息* @return* */@Overridepublic String toString() {return "LigerUiTree [name=" + name + ", level=" + level + ", url=" + url + ", id=" + id+ ", nodeType=" + nodeType() + ", isexpand=" + isexpand + "]";}}

在LigerUiTree中,我们使用了递归来遍历树。这个代码不难,就是普通的一些树的常用操作。为了测试,我们需要一个工具类,用来输出这个树的数据结果:

package net.itaem.ligerui;import java.util.List;/*** * 这个类用来输出树的结构信息,为了方便测试* @author 骆宏* @date 2014-08-19* @email 846705189@qq.com* */
public class LigerUiTreeTool {/*** 以下面个数来输出树* root*   --child1*   --child2*     --child-child1*     --child-child2*   --child-3* */public static void printTree(ITreeModel tree){if(tree == null) return;if(tree.parent() == null){   //输出根节点的名字System.out.println(tree.name());}List<ITreeModel> children = tree.children();if(children != null){level++;for(int i=0; i<children.size(); i++){for(int j=0; j<level; j++){System.out.print("  ");}System.out.println("--" + children.get(i).name());if(children.get(i).children() != null)printTree(children.get(i));else if(i == children.size()-1){level = 1;  }}}}//用来辅助输出的一个level,用来计算输出空格private static int level = 1;
}

上面的类是用于输出树的,没有大的实际意义。在这个工具树种,我们使用了广度遍历。一般情况下,树的遍历有两种。一种是广度遍历,另外一种则是深度遍历。大家有兴趣可以百度下相关定义以及概念。

    代码差不多了,直接写个测试吧。

    

package net.itaem.test;import java.util.ArrayList;
import java.util.List;import net.itaem.ligerui.ITreeModel;
import net.itaem.ligerui.LigerUiTree;
import net.itaem.ligerui.LigerUiTreeTool;/*** 测试liger ui的树模型* */
public class LigerUiTreeTest {public static void main(String[] args){ITreeModel root = new LigerUiTree("ROOT", "根节点", "localhost/root");List<ITreeModel> children = new ArrayList<ITreeModel>();//生成一个1 * 10 * 3三个层次的树模型for(int i=0; i<10; i++){ITreeModel child = new LigerUiTree("child-" + i, "child-name-" + i, "localhost/child-" + i);List<ITreeModel> childChildren = new ArrayList<ITreeModel>();for(int j=0; j<3; j++){ITreeModel childChild = new LigerUiTree("children-" + i + "" + j, "child-children-child-" + i + "" + j, "localhost/child/children-" + i + "" + j);childChildren.add(childChild);}child.setChildren(childChildren);children.add(child);}root.setChildren(children);System.out.println("======================whole tree=======================");LigerUiTreeTool.printTree(root);System.out.println("=======================基本信息================================");System.out.println(root);System.out.println("==========================subTree==============================");//输出根节点的子树List<ITreeModel> subTree = root.children().get(0).subTree();System.out.println(subTree);System.out.println("==========================route================================");//测试叶子节点到根节点的所有节点ITreeModel leaf = root.children().get(0).children().get(0);System.out.println(leaf.route());System.out.println("==========================after change=========================");//测试修改名字,url,name,id,isexpend等属性root.setName("change name");root.setId("change id");root.setIsexpand(true);root.setUrl("change url");System.out.println(root);System.out.println("==============================liger ui tree json==========================");System.out.println(root.toTreeJson());}
}

下面是程序输出结果:

    

======================whole tree=======================
根节点
--child-name-0
--child-children-child-00
--child-children-child-01
--child-children-child-02
--child-name-1
--child-children-child-10
--child-children-child-11
--child-children-child-12
--child-name-2
--child-children-child-20
--child-children-child-21
--child-children-child-22
--child-name-3
--child-children-child-30
--child-children-child-31
--child-children-child-32
--child-name-4
--child-children-child-40
--child-children-child-41
--child-children-child-42
--child-name-5
--child-children-child-50
--child-children-child-51
--child-children-child-52
--child-name-6
--child-children-child-60
--child-children-child-61
--child-children-child-62
--child-name-7
--child-children-child-70
--child-children-child-71
--child-children-child-72
--child-name-8
--child-children-child-80
--child-children-child-81
--child-children-child-82
--child-name-9
--child-children-child-90
--child-children-child-91
--child-children-child-92
=======================基本信息================================
LigerUiTree [name=根节点, level=3, url=localhost/root, id=ROOT, nodeType=menu, isexpand=false]
==========================subTree==============================
[LigerUiTree [name=child-name-0, level=2, url=localhost/child-0, id=child-0, nodeType=menu, isexpand=false], LigerUiTree [name=child-children-child-00, level=0, url=localhost/child/children-00, id=children-00, nodeType=leaf, isexpand=false], LigerUiTree [name=child-children-child-01, level=0, url=localhost/child/children-01, id=children-01, nodeType=leaf, isexpand=false], LigerUiTree [name=child-children-child-02, level=0, url=localhost/child/children-02, id=children-02, nodeType=leaf, isexpand=false]]
==========================route================================
[LigerUiTree [name=根节点, level=3, url=localhost/root, id=ROOT, nodeType=menu, isexpand=false], LigerUiTree [name=child-name-0, level=2, url=localhost/child-0, id=child-0, nodeType=menu, isexpand=false], LigerUiTree [name=child-children-child-00, level=0, url=localhost/child/children-00, id=children-00, nodeType=leaf, isexpand=false]]
==========================after change=========================
LigerUiTree [name=change name, level=3, url=change url, id=change id, nodeType=menu, isexpand=true]

哈哈,测试完毕,然后就可以使用Action,将树的数据携带到jsp中,那么一个ligerui的树插件就搞定了。


liger ui组件的抽取与封装相关推荐

  1. 【封装UI组件库】手把手教你仿一下Element-ui的Button组件(发布至npm)

    所谓UI组件库,就是封装了平常项目开发中经常会使用的页面组件,发布至npm库中作为插件供项目组成员及其他开发者使用(不发布也行),目的就是为了避免多次重复劳动. 以插件的形式使用可以做到即插即用,非常 ...

  2. Element ui 组件中用键盘事件

    //这是表单 <el-form:model="ruleForm"status-icon:rules="rules"ref="ruleForm&q ...

  3. 如何在uni-app中选择一个合适的UI组件库

    uni-app框架转眼已经发布了一年多,使用uni-app的开发者也是与日俱增.因为uni-app是一个跨端框架,所以我们大多使用它就是为了同时一套代码跨多端,选择uni-app 可以算是眼下一个比较 ...

  4. 封装html ui 控件,聊聊前端 UI 组件:组件设计

    本文首发于欧雷流.由于我会时不时对文章进行补充.修正和润色,为了保证所看到的是最新版本,请阅读原文. 在本系列文章<聊聊前端 UI 组件:组件体系>中初步说明了 UI 组件的架构设计,本文 ...

  5. 初探 amaze-vue( 基于vue.js封装的Amaze UI 组件库)

    Amaze UI 是以移动优先(Mobile first)为理念,面向 HTML5 开发的国产优秀组件库.因官方未提供vue.js版本,而且民间一直对vue.js版本的 Amaze UI 组件库呼声很 ...

  6. LuLu UI - 腾讯阅文集团出品的“半封装” 开源 Web UI 组件库,特点是面向设计、简单灵活、支持 Vue

    阅文集团前端大神张鑫旭的团队出品的面向设计的前端 UI 组件库,上手简单,定制性强. 关于 LuLu UI LuLu UI 是一款面向桌面端和移动端网页开发的组件库,由阅文集团前端团队出品.阅文集团由 ...

  7. Chrome学习笔记(二):UI组件,皮肤引擎

    原创文章,转载请注明:转载自Soul Apogee 本文链接地址:Chrome学习笔记(二):UI组件,皮肤引擎 -- 基础设施篇 Chrome的UI是很奇妙的,因为看起来能很好的跨平台,而且可以很好 ...

  8. 用vue优雅地编写UI组件的几条指导原则

    前言 最近在尝试写几个UI组件,并通过阅读element-ui的源码,与其反复比较,然后认真思考,最后总结出一些自己的一些心得和体会.在造轮子的过程中,既巩固了html,css,js基础,又加深了对v ...

  9. 【分享】Vue 资源典藏(UI组件、开发框架、服务端、辅助工具、应用实例、Demo示例)...

    Vue 资源典藏,包括:UI组件 开发框架 服务端 辅助工具 应用实例 Demo示例 element ★11612 - 饿了么出品的Vue2的web UI工具套件 Vux ★7503 - 基于Vue和 ...

最新文章

  1. 转 spring配置文件
  2. 对话百度贾磊/喻友平:深度学习正往跨领域融合高速发展
  3. 车载信息安全企业自发成立联盟
  4. iOS底层面试题--RunLoop
  5. boost::test模块测试可变参数样本元素支持和数据集定义的移动语义
  6. C# WebApi POST 提交
  7. oracle decode别名,Oracle中decode函数用法 VelHong
  8. SQLi LABS Less 16 布尔盲注
  9. linux之grep使用技巧
  10. OSG 初始化为非全屏窗口
  11. hive 安装centos7
  12. 存储知识学习之--IP网络存储iSCSI的概念与工作原理
  13. 在html中怎样使用%3c符号,5个JavaScript和9个JQuery经典面试题
  14. 计算机处理问题的数学模型分为哪两类,数据模型与决策习题与参考答案
  15. 高通SDX12:sar sensor AW9610x驱动移植
  16. 信息系统项目管理师 - 必考记忆口诀
  17. 思科VPLS解决方案
  18. 9月24号面试总结(康拓普1面)
  19. 酷狗音乐下载|酷狗音乐播放器下载
  20. Nginx+keepalived 高可用双机热备(主从模式/双主模式)

热门文章

  1. 分析函数hive计算均值_Hive中的函数
  2. linux中八进制数对应符号,八进制
  3. Untiy 灯光属性介绍
  4. Keil5新建stm32工程
  5. 1069 微博转发抽奖 (20 分)(C语言)
  6. 西门子博途编程-模拟量批量处理一
  7. 如何在Oracle官网下载JAVA SE 8版本(JDK 1.8.0)
  8. (转载):ganglia之环境搭建部署
  9. mac安装protobuf
  10. PCF8591组件(A/D和D/A转换)