`
chenxueyong
  • 浏览: 342320 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

ExtJs中的树分析及实现

阅读更多

<网上抄录>

首先我们来看日志分类树,这一部分我将重点给大家分析ExtJS中的树,以及本示例中树的详细实现,包括如何与服务器进行数据交互,如果响应处理树及节点上的各个事件等.

树的显示:

首先,我们来看看日志管理菜单中包含异步树的代码,如下所示:

var categoryNode=new Ext.tree.AsyncTreeNode({

id:'root',

text:'日志内容管理',

loader.topicCategoryLoader

});

this.root.appendChild(categoryNode);

this.on('click',function(node.eventObject){

......//事件处理代码

});

日志内容管理这个节点下面就是日志分类子节点,这些节点都是异步加载的,所以需要给这个节点定义一个加载器,默认情况下,该节点的子节点也会使用父节点来加载其下面节点的数据.加载这些节点的加载器是topicCategoryLoader,topicCategoryLoader在manager.js中的定义,内容如下:

topicCategoryLoader:new Ext.tree.TreeLoader({

   url:"topicCategory.ejf?cmd=getCategory&pageSize=1&treeData=true",

listeners:{

      'beforeload':function(treeLoader,node){

        treeLoader.baseParams.id=(node.id!='root'?node.id:"");

   }

}

})

        url参数表示可以得到节点JSON数据的url地址.由于在TreeLoader中定义了beforeload事件响应函数,也就是在第一次要到服务器加载树节点信息之前,都会执行该响应函数,该事件响应函数可以带两个参数,第一个参数是指准备加载数据的TreeLoader对象,第二个参数是node表示要加载的节点.

       在响应函数中我们设置了加载器中baseParams对象的id属性值为所要加载节点的id或者空字符,根据当前节点的id值来判断.也就是说如果是加载id为root的节点,其会给服务器传递一个字符为空的id查询参数,类似于访问下面的url "/topicCategory.ejf?cmd=getCategory&pageSize=-1&treeData=true&id=";如果id为root以为的其他节点时,就是加载root节点的子节点的子节点(或孙子,重孙子节点时),都会把要加载的节点的id值作为参数传给服务器端,类似于直接访问url "/topicCategory.ejf?cmd=getCategory&pageSize=-1&treeData=true&id=xxx".

       服务器端返回节点为JSON数据格式,是一个包含各个节点对象的信息数组,如下所示:

[{

   id:1,

   text:"叶子节点1",

   leaf:true

},{

id:2,

   text:"叶子节点2, 包含子节点",

children:[{

   id: 3,
            text: '节点的子节点',
            leaf: true
        }]
}]

 由于每一个节点都是异步加载的,也就是只有在需要的时候才会到服务器加载这个子节点下的节点内容,因此不会一次性返回节点的children,异步加载的时候服务器返回的信息应该如下所示:
[{
        id: 1,
        text: '叶子节点1',
        leaf: true
    },{
        id: 2,
        text: '节点2,包含子节点',
        leaf: false
   }]

   注意,节点2由于还有子节点,所以其leaf属性值为false。这样Ext在构造这个节点的时候,会把该节点创建成一个节点加载节点,当我们点击该节点时又会再一次到服务器端加载数据。

       因此, topicCategory.ejf?cmd=getCategory&pageSize=-1&treeData=true这个url返回也就是一个JSON数据,包含了各个子节点的对象数组信息,在看这个url具体返回的内容之前,我们先看看topicCategory这段上模块后台代码.

后台数据加载

  topicCategory这个模块的Action为TopicCategoryAction,该类的命令处理方法只有一个,即用于提供树节点JSON数据的doGetCategory方法,代码如下:
@Action
public class TopicCategoryAction extends BaseAction {//继承BaseAction使得该模块的所有内容只有管理员才能访问
@Inject//表示自动注入这个service,由于前面使用@Action标签,所以这里其实可以省略
private ITopicCategoryService service;
//getCategory命令处理方法
public Page doGetCategory(WebForm. form)
{  
   String id=CommUtil.null2String(form.get("id"));//得到客户端不的查询参数id值
QueryObject query=form.toPo(QueryObject.class);//根据客户端的请求信息创建查询对象,由于请求的url中包含一个pageSize=-1的查询参数及值,所以这里会把调用queryObject.setPageSize方法把返回的数据设置为-1,也就是无限
if(!"".equals(id))//如果id不为空
   {
   TopicCategory parent=this.service.getTopicCategory(new Long(id));
   query.addQuery("obj.parent",parent,"=");//在查询对象中添加一个查询条件,表示查询parent为指定id的分类
   }
   else
   {
    query.addQuery("obj.parent is EMPTY",null);//否则,查询所有的根节点,这里使用的是标准的JPA对象查询语句
   }
   IPageList pageList=this.service.getTopicCategoryBy(query);//通过service的日志分类查询方法查询分类对象
   //然后是处理从业务层得到的查询数据,把他们转换成Ext树加载器需要的JSON格式
   String treeData = CommUtil.null2String(form.get("treeData"));
   if ("".equals(treeData)) {// 获得pageList的数组
   //这里省略这一部分,将在日志分类管理表格中用到
   }
   else{//这里表示为分类树提供信息
   List<Node> nodes=new java.util.ArrayList<Node>();//创建一个代表树节点的List
   if(pageList.getRowCount()>0){//如果数据库中查询到节点
   for(int i=0;i<pageList.getResult().size();i++)//循环每一个查询到的TopicCategory
   {
    TopicCategory category=(TopicCategory)pageList.getResult().get(i);
    nodes.add(new Node(category));//把TopicCategory转换成Node对象,并添加到返回列表中
   }
   }
   else//如果没有查询到任何节点,则创建一个“无分类”的节点返回给客户端
   {
   TopicCategory c=new TopicCategory();
   c.setName("无分类");
   c.setId(0l);
   nodes.add(new Node(c));
   }
   form.jsonResult(nodes);//把所有的树节点nodes作为json返回节点存放到form中
   }
   return Page.JSONPage;//返回JSON页面模板
}

  下面是代表客户端树节点信息一的Node类的定义,代码内容及详细注解如下:
private class Node {
   private TopicCategory category;
   Node(TopicCategory category)//接受一个TopicCategory为参数来构造节点
   {
    this.category=category;
   }
   public String getId() {   //获得节点的id
    return category.getId().toString();
   }
   public boolean getLeaf() {   //该节点是否是叶子节点
    return category.getChildren().size()<1;
   }  
   public String getText() {    //该节点的显示文本
    return category.getName();
   }
   public String getQtip()//该节点的快速提示信息
   {
    return category.getName();
   }
}
}

在浏览器输入地址:
topicCategory.ejf?cmd=getCategory&pageSize=-1&treeData=true

你会得到类似下面的内容:
function(){var v0=[];var v1={};var v6={};var v11={};var v16={};var v21={};var v26={};var v31={};var v36={};var v41={};var v46={};var v51={};var v56={};v1.id="1".replace(/"/g, '"');v1.leaf=false;v1.qtip="JAVA".replace(/"/g, '"');v1.text="JAVA".replace(/"/g, '"');v6.id="2".replace(/"/g, '"');v6.leaf=true;v6.qtip="Dot\ Net".replace(/"/g, '"');v6.text="Dot\ Net".replace(/"/g, '"');v11.id="3".replace(/"/g, '"');v11.leaf=true;v11.qtip="PHP".replace(/"/g, '"');v11.text="PHP".replace(/"/g, '"');v16.id="4".replace(/"/g, '"');v16.leaf=true;v16.qtip="ASP".replace(/"/g, '"');v16.text="ASP".replace(/"/g, '"');v21.id="5".replace(/"/g, '"');v21.leaf=true;v21.qtip="ROR".replace(/"/g, '"');v21.text="ROR".replace(/"/g, '"');v26.id="6".replace(/"/g, '"');v26.leaf=true;v26.qtip="Python".replace(/"/g, '"');v26.text="Python".replace(/"/g, '"');v31.id="7".replace(/"/g, '"');v31.leaf=true;v31.qtip="ExtJS\u6587\u7AE0".replace(/"/g, '"');v31.text="ExtJS\u6587\u7AE0".replace(/"/g, '"');v36.id="65536".replace(/"/g, '"');v36.leaf=false;v36.qtip="Other".replace(/"/g, '"');v36.text="Other".replace(/"/g, '"');v41.id="65543".replace(/"/g, '"');v41.leaf=false;v41.qtip="\u5FC3\u60C5".replace(/"/g, '"');v41.text="\u5FC3\u60C5".replace(/"/g, '"');v46.id="65544".replace(/"/g, '"');v46.leaf=true;v46.qtip="\u5FC3\u60C5".replace(/"/g, '"');v46.text="\u5FC3\u60C5".replace(/"/g, '"');v51.id="65546".replace(/"/g, '"');v51.leaf=true;v51.qtip="\u7F51\u7EDC\u65E5\u5FD7".replace(/"/g, '"');v51.text="\u7F51\u7EDC\u65E5\u5FD7".replace(/"/g, '"');v56.id="65547".replace(/"/g, '"');v56.leaf=true;v56.qtip="\u554A\u554A".replace(/"/g, '"');v56.text="\u554A\u554A".replace(/"/g, '"');v0[0]=v1;v0[1]=v6;v0[2]=v11;v0[3]=v16;v0[4]=v21;v0[5]=v26;v0[6]=v31;v0[7]=v36;v0[8]=v41;v0[9]=v46;v0[10]=v51;v0[11]=v56;return v0;}()

 

  你不用担心你看不懂,这是一个经过压缩及转码后json数据,他是直接把服务器端的对象自动转换成的,由于我们返回的json数据nodes类型为list,所以返回给端的时候会变成一个数组,数组中的每一元素都是Node对象,包含getter方法中定义的属性及值,如leaf、text、id等。

捕捉事件

  在日志分类树的菜单中,我们点击内容管理中某一个子节点的时候,都需要在主工作区中打开该分类的日志内容管理面板,要实现该功能,就需要定义节点的事件响应函数,这里是click事件响应,其代码及详细注解如下所示:
on方法是addListener方法的缩写,用于给组件添加事件响应函数(也可以理解为事件监听器或事件处理器)
this.on("click",function(node,eventObject)//树的click事件响应函数可以包含两个参数,第一个表示当前点击的节点node,第二个表示Ext的事件对象
   {
   if(node==categoryNode||categoryNode.contains(node)){//首先判断点击的节点是不是属于内容管理节点,或者是内容管理节点下面的子节点,如果是则执行下面的操作。如果点击的是其它节点,比如菜单中的“写日志”则不用管。
      var panel=Ext.getCmp("topicListPanel");//得到日志内容管理面板
      if(!panel){
        panel=new TopicListManage();//如果没有,则直接用new创建一个
        removeTopic=function(id){//给全局的函数removeTopic赋初值
         panel.grid.getSelectionModel().selectRecords([panel.store.getById(id)]);//选中表格中指定id的记录
         panel.removeData();//调用面板的removeData方法删除数据
};
        editTopic=function(id){//给全局的editTopic函数赋值
         panel.grid.getSelectionModel().selectRecords([panel.store.getById(id)]);//在表格中选中指定id的行
         panel.edit();//调用表格的edit方法来编辑选中的行
         };
       }
      main.openTab(panel);//在主工作区中打开内容管理面板,并设置成当前活动面板
   panel.store.baseParams.categoryId=(node.id!='root'?node.id:"");//根据当前点击的节点指定表格中数据加载时传递的categoryId值
      panel.store.removeAll();//首先删除表格中所有数据
      panel.store.reload();//然后重新加载表格中的数据
   }

另外一颗树

  日志分类树除了菜单面板中这一棵以外,当点击分类管理的时候,日志分类管理程序中也会出现另外一棵树,如下图所示:

  日志分类管理里面的这一树树比较简单,就是直接是一树普通的树而已,其仍然是使用topicCategoryLoader作为树节点数据加载器。定义这棵树的代码及注解如下:
//直接调用new方法来初始化一个Ext.tree.TreePanel面板,用来显示树结构的信息
this.tree=new Ext.tree.TreePanel({title:"日志分类",//树面板的标题
     region:"west",//面板所在区域
     width:150,//面板的宽度
     root:new Ext.tree.AsyncTreeNode({//树根为一棵异步加载树
      id:"root",//树跟的id为特殊值root
        text:"日志分类", //定义树根显示的文本
        expanded:true,//可以展开
        loader:topicCategoryLoader//指定根节点的加载器
    });

这棵树的事件响应函数也比较简单,就是根据节点的信息直接重新加载表格中的数据。其代码及注解如下:
//调用组件的on方法来添加事件响应函数,参数click表示添加针对click事件的响应函数
this.tree.on("click",function(node,eventObject){//响应函数包含两个参数,第一个表示当前点击的节点
var id=(node.id!='root'?node.id:"");//得到日志分类对象的真实id
this.store.baseParams.id=id;//设置表格中的加载子节点时的id
this.store.removeAll();//删除表格中的所有数据
this.store.load();//重新加载表格中的数据
},this); //最后一个参数this表示事件响应函数的作用域为this

分享到:
评论

相关推荐

    EXTJS 4 树形表格组件使用示例

    在提供的压缩包文件"extjs4.1_TreeGrid"中,可能包含了一些EXTJS 4树形表格组件的示例代码和资源,通过学习和分析这些示例,你可以更好地理解如何在项目中应用这个组件。 总结来说,EXTJS 4的树形表格组件是一个...

    extjs动态树struts请求数据

    通过分析和学习这个文件,可以更深入地理解ExtJS和Struts如何协作实现动态树功能。 总结以上,ExtJS动态树与Struts的结合使用,需要熟练掌握ExtJS TreePanel的配置,JSON数据的构造和解析,以及Struts2的Action和...

    ExtJs树例子

    在"ExtJs树例子"这个主题中,我们主要关注的是ExtJS如何实现树形控件(Tree Panel)。 树形控件在Web应用中广泛用于展示层次结构的数据,比如文件系统、组织架构或菜单导航。ExtJS提供了一个完善的TreePanel组件来...

    Extjs 动态加载树

    1. **Extjs TreePanel**: TreePanel是Extjs中用于展示树形数据的组件,它允许你创建可交互的树结构。动态加载通常通过配置TreePanel的`rootVisible`、`loadMask`、`async`属性以及`loader`来实现。 2. **异步加载**...

    Extjs自定义组件-下拉树

    本文将围绕“Extjs自定义组件—下拉树”这一主题,详细阐述其实现原理、使用方法以及核心代码分析。 #### 一、理解下拉树组件 下拉树组件结合了下拉框(ComboBox)与树形结构(Tree),旨在提供一种直观、高效的...

    Extjs4 下拉树( v1.0版本有bug,已经上传一个可以用的)

    标题中的“Extjs4 下拉树”指的是EXTJS框架中的一个组件,用于实现下拉菜单与树形结构的结合,这种组件通常在需要选择层级结构数据时非常有用,比如地区选择、组织架构选择等。EXTJS是Sencha公司开发的一个...

    ExtJS5.0 树形菜单实例

    在ExtJS 5.0 版本中,TreePanel 是实现树形结构数据展示的重要组件,常用于构建如文件系统、组织架构或层级关系的菜单。下面我们将深入探讨如何利用ExtJS 5.0 创建一个树形菜单实例。 1. **TreePanel 基础** ...

    Extjs实现下拉菜单效果

    在本篇文章中,我们将详细了解如何使用ExtJS框架实现具有下拉树功能的下拉菜单效果。ExtJS是一个成熟的JavaScript框架,用于创建交互式的Web应用程序,提供了一整套丰富的用户界面组件,其下拉树组件是其众多组件之...

    extjs动态树的示例代码.rar

    ExtJS 是一个强大的JavaScript框架,...通过分析和学习这段代码,你可以更好地理解和应用ExtJS动态树的实现方式。记住,实际项目中可能还需要结合服务器端的接口设计和数据格式,确保数据能正确地加载到树形结构中。

    用ExtJS实现动态载入树

    ### 用ExtJS实现动态载入树的知识点详解 #### 一、背景介绍与需求分析 在企业级应用开发中,树形结构是一种常见的数据展示形式,尤其在组织架构、文件系统等方面应用广泛。本文将详细介绍如何利用ExtJS框架来实现...

    带复选框的 ExtJs tree

    综上所述,“带复选框的ExtJS tree”这一主题深入探讨了如何在ExtJS框架中实现具有复选框功能的树形结构。通过对标题、描述、标签和部分内容的分析,我们可以看到这是一个关于ExtJS TreePanel高级用法的案例,涉及到...

    Extjs3.2中文帮助手册

    2. **组件系统**:ExtJS的核心是其组件系统,包括各种UI元素如按钮、表单、面板、树形视图、表格等。手册将详细解释每个组件的属性、方法和事件,以及如何创建和配置这些组件。 3. **布局管理**:ExtJS提供多种布局...

    extjs实现报表

    在"extjs实现报表"这个主题中,我们将深入探讨如何利用ExtJS来设计和实现各种类型的报表。 1. **ExtJS报表基础** - **数据绑定**:ExtJS支持双向数据绑定,可以轻松地将数据显示在UI上,并实时更新数据变化。 - *...

    ExtJS4中文教程2 开发笔记 chm

    Jquery中显示隐藏的实现代码分析 JQuery全选功能的实现 JQuery特效——下拉菜单 JQuery系列教程之XPath选择符 JQuery系列教程之选择符 JQuery自动缩放页面中的图片 JQuery获取浏览器的高度和宽度 jquery获得和设置...

    EXTjs4.2中文版

    EXTjs4.2中的图表组件得到了显著提升,提供了丰富的图表类型,包括柱状图、饼图、线图等,可以动态展示和交互,为数据分析和可视化提供了强大的工具。此外,4.2版本还改进了表格组件,增加了行编辑、列拖动等功能,...

    extjs组织架构图

    在本案例中,"extjs组织架构图"是一个利用ExtJS框架实现的交互式、可伸缩的组织结构展示工具。 组织架构图是表示一个组织内部部门、职位或员工之间关系的图表,通常表现为树状结构。这种图表有助于理解公司的层级...

    extJS3.1源码及demo

    在"extJS3.1源码及demo"这个资源中,你将找到ExtJS 3.1.0的完整源代码和相关的示例。源码的分析对于深入理解框架的工作原理至关重要,特别是对于那些想要进行定制化开发或者优化性能的开发者来说。源码包含了各种...

    ExtJs4实现下拉树选择框ComboTree

    ### ExtJs4 实现下拉树选择框 ComboTree #### 概述 在现代Web应用开发中,ExtJS 是一个非常强大的JavaScript库,用于构建复杂的客户端应用程序。它提供了丰富的组件库,使得开发者能够轻松地创建出功能丰富且交互性...

    实例分析ExtJs

    **ExtJs概述** ExtJs是一款基于JavaScript的开源前端框架,主要应用于构建富互联网应用程序(RIA)。...在`ext_project1`这样的实例中,我们可以看到ExtJs在实际场景中的运用,进一步学习和掌握其使用技巧。

Global site tag (gtag.js) - Google Analytics