首页 > 代码库 > 树(选自《掏钱学习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》)