首页 > 代码库 > 树(选自《掏钱学习EXT》)

树(选自《掏钱学习EXT》)

一.何为树

树是一种典型的数据结构。

1.2.0版本中的数实现

var tree = new Ext.tree.TreePanel({         el:tree });

此时用firebug看dom,height是0,因为2.0里的树是不会自动伸缩的,我们在和html里面给予一个高度

<div id = ‘tree‘  style=‘height:300px;‘></div>

接着,我们要做一个树根:

var root  = new Ext.tree.treeNode((text:‘偶是根‘));

  var root = new Ext.tree.TreeNode({text:‘偶是根‘});
  var node1 = new Ext.tree.TreeNode({text:‘偶是根的第一个枝子‘});
  var node2 = new Ext.tree.TreeNode({text:‘偶是根的第一个枝子的第一个叶子‘});
  var node3 = new Ext.tree.TreeNode({text:‘偶是根的第一个叶子‘});
  node1.appendChild(node2);
  root.appendChild(node1);
  root.appendChild(node3);

tree.setRootNode(root);tree.render();

看看效果:

2.这样装配树节点的形式,真是让人头大

Ext.tree.Treeloader可以和后台进行数据的交换,我们提供数据,让TreeLoader帮我们做数据转换和装配节点的操作。

首先我们要加上treeloader:

var tree = new Ext.tree.TreePanel(‘tree‘,{       loader:new Ext.tree.TreeLoader({dataUrl:‘03-03.txt‘})});

dataurl表示渲染后去哪儿读取数据,我们模拟一个文本提供数据,打开一个叫做03-03.txt的文本,里面有

[ {text:‘not leaf‘}, {text:‘is leaf‘,leaf:true}]

里面是一个包含两个节点的数组,可能你会发现那个多出来的属性是leaf:true。

此次还要强调的一点是,TreeNode不支持ajax的,我们需要把根节点换成AsyncTreeNode,它可以实现。

var root = new Ext.tree.AsyncTreeNode({text:‘偶是根‘});

但是,令人沮丧的是,会出现这种无限延展的效果

所以我们要把root.expand(true,true)改成root.expand()。取消了递归展开,只展开第一层节点。

AsyncTreeNode继承根节点的dataUrl,你展开的时候会执行这个节点的expand()方法,id会作为参数传递给dataUrl,后台就可以通过这个节点的id计算出该返回什么数据,得到了数据treeloader去解析数据并且装配成子节点,然后显示出来。

但是03-03里面的数据不会判断当前节点的id,所以每次返回数据都是一样的,就会无限循环下去。

其实这种异步读取是一件很爽的事情,不会点击一次把全部数据装载和渲染一遍。

我们写个稍微复杂的例子

在03-04.txt里写入

[  {text:‘01‘,children:[           {text:‘01-01‘,leaf:true},           {text:‘01-02‘,children:[                  {text:‘01-02-01‘,leaf:true},                  {text:‘01-02-02‘,leaf:true}]},           {text:‘01-03‘,leaf:true}]},           {text:‘02‘,leaf:true} ]

这也可以看作是数据不多的情况下,一次加载所有数据的途径只是确保所有叶子节点上都加上leaf:true的属性,就不会出现循环展开的问题了。

3.jsp的例子一定要有

如果没有jsp例子,就不知道怎么判断目前要展开哪个节点。先把dataUrl改成tree.jsp

var tree = new Ext.tree.treePanel(‘tree‘,{             loader:new Ext.tree.TreeLoader({dataUrl:‘tree.jsp‘}) });

在root节点设置一个id,这样后台就知道什么时候在读取根节点了

var root = new Ext.tree.AsynTreeNode({           id:‘0‘,           text:‘偶是根‘});

我们设置了一个id:“0”,注意id不要出现重复,我们马上就要根据id来判断究竟是哪个节点正在展开。

我们看看后台:

树形异步读取关键点在node参数,当一个节点展开的时候,会让treeloader根据设置的dataUrl发送请求去后台读取数据,发送请求的时候treeloader会把这个节点的id作为参数一并发送到后台去对去后台来说,只要获得node参数,只要获得node参数想展开哪儿就是哪儿。

再根据节点的id返回对应的json数据,返回的时候记得返回id和text就可以了,id是后台读取的id,text就是节点名称。

展开后的效果为:

这里有个问题,我们并没有标记谁是树叶(leaf:true),但是AsynTreeNode在后台读取数据时,后台没有明显返回任何子节点数据,这时候asynctreeNode会自动把最下层的child置为叶子。

但是后台访问也会消耗服务器的带宽,为了减少这样的压力。

直接在叶子后加{leaf:true}

4.检阅树的事件

ext的事件模型可以告诉你很多事情,我们使用on注册事件监听器就行了:

tree.on("expand",function(node){            Ext.log(node+"展开了");});tree.on("collapse",function(node){            Ext.log(node+"折叠了");});tree.on("click",function(node){            Ext.log(node+"你单击了");});tree.on("dbclick",function(node){            Ext.log(node+"双击了");});

让我我们随意点一气:

其实on("eventName")就是把一个函数绑定到一个事件上。

还有,

还可以自定义右键菜单,注册一个名为contextmeun的事件。

第一步:制作自定义菜单

var contextmenu = new Ext.menu,Menu(   id:‘theContextMenu‘,   items:[{         text:‘有本事点我哦!‘,         handler:function(){              alert("我被击中了,啊。。。")}   }]);

第二部,绑定contextmenu事件

tree.on("contextmenu",function(node,e){     e.preventDefault();     node.select();     contextmenu.showAt(e.getXY())    });

这个事件绑定的函数传递两个参数,首先调用的是e.preventDefault()防止浏览器弹出它默认的功能菜单。

然后node.select()选中当前节点,showAt(e.getXY()),获得当前鼠标的坐标。我们还需要用到contextmenu.hide(),加在展开等行为前。

接下来的功能有:

更换图标,从节点弹出对话框,自动弹出小提示,给节点设置超链接,直接修改节点名称,自由拖动

 等等。。。。。。。在此,就不一一介绍了。

树(选自《掏钱学习EXT》)