树控件
ExtJS 中提供了现存的树控件,通过这些控件可以在B/S 应用中快速开发出包含树结构信息的应用。
A:TreePanel
基本使用
树控件由Ext.tree.TreePanel 类定义,控件的名称为treepanel,TreePanel 类继承自Panel面板。在ExtJS 中使用树控件其实非常简单,我们先来看下面的代码。
代码的第一句使用new Ext.tree.TreeNode 类来创建一个树节点,第二句使用树节点的root 的appendChild 方法来往该节点中加入一个子节点,最后直接使用new Ext.tree.TreePanel来创建一个树面板,要树面板的初始化参数中指定树的root 属性值为前面创建的root 节点,也就是树根节点。
ExtJS 的树控件提供了对这种功能的支持,你只需要在创建树控件的时候,通过给树指定一个节点加载器,可以用来从服务器端动态加载树的节点信息。我们来看下面的代码:
Ext.onReady(function(){
var root=new Ext.tree.TreeNode({
id:"root",
text:"树的根"});
root.appendChild(new Ext.tree.TreeNode({
id:"c1",
text:"子节点"
}));
var tree=new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:100
});
});
代码的第一句使用new Ext.tree.TreeNode 类来创建一个树节点,第二句使用树节点的root 的appendChild 方法来往该节点中加入一个子节点,最后直接使用new Ext.tree.TreePanel来创建一个树面板,要树面板的初始化参数中指定树的root 属性值为前面创建的root 节点,也就是树根节点。
ExtJS 的树控件提供了对这种功能的支持,你只需要在创建树控件的时候,通过给树指定一个节点加载器,可以用来从服务器端动态加载树的节点信息。我们来看下面的代码:
var root=new Ext.tree.AsyncTreeNode({
id:"root",
text:"树的根"});
var tree=new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
loader: new Ext.tree.TreeLoader({url:"treedata.js"}),
width:100
});
treedata.js 这个url 返回的内容如下:
[{
id: 1,
text: '子节点1',
leaf: true
},{
id: 2,
text: '儿子节点2',
children: [{
id: 3,
text: '孙子节点',
leaf: true
}]
}]
执行上面的程序,可以得到一棵异步加载子节点的树,点击”根节点”会到服务器端加载子节点
当然上面的程序是一次性加载完了树的所有节点信息,我们也可以实现让每一个节点都支持动态加载的树,只需要在通过服务器请求数据的时候,每次服务器端返回的数据只只包含子节点,而不用把孙子节点也返回即可。比如把上面treedata.js 中的内容改为下面的内容:
[{
id: 1,
text: '子节点',
leaf: false
}]
也就是节点树中只包含一个子节点,而该子节点通过指定leaf 值为false (默认情况该值为false),表示该节点不是一个叶子节点,其下面还有指节点。
当然这是一个无限循环的树,在实际应用中我们服务器端返回的数据是程序动态产生的,因此不可能每一次都产生leaf 为false 的节点,如果是叶子节点的时候,则需要把返回的JOSN 对象中的leaf 设置为true。如下所示:
[{
id: 1,
text: '子节点',
leaf:true
}]
事件处理
当然,仅仅能显示一棵树还不够,我们一般还需要在用户点击树节点的时候执行相应的东西,比如打开某一个连接,执行某一个函数等,这就需要使用到事件处理。比如下面的代码:
Ext.onReady(function(){
var root=new Ext.tree.TreeNode({
id:"root",
text:"树的根"});
var c1=new Ext.tree.TreeNode({
id:"c1",
text:"子节点"
});
root.appendChild(c1);
var tree=new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:100
});
tree.on("click",function(node,event){
alert("您点击了"+node.text);
}
);
c1.on("click",function(node,event){
alert("您点击了"+node.text);
}
);
});
执行上面的程序,当用户点击树控件中的任意节点时,都会弹出一个提示信息框,当用户点击c1 这个子节点时,会弹出两次提示信息框。因为我们除了指定tree 的click 事件响应函数以外,另外又给node 节点指定单独的事件响应函数。
当然,如果只是要实现当点击树节点时跳到某一个指定url 的功能则非常简单。看下面的代码:
Ext.onReady(function(){
var root=new Ext.tree.TreeNode({
id:"root",
href:"http://www.baidu.com",
hrefTarget:"_blank",
text:"树的根"});
var c1=new Ext.tree.TreeNode({
id:"c1",
href:"http://www.baidu.com",
hrefTarget:"_blank",
text:"子节点"
});
root.appendChild(c1);
var tree=new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:100
});
});
执行程序,点击树节点,将会在浏览新窗口中打开节点中href 指定的链接在ExtJS 中,不管是叶子节点还是非叶子节点,都统一用TreeNode 表表示树的节点。在ExtJS 中,有两种类型的树节点。一种节点是普通的简单树节点,由Ext.tree.TreeNode 定义,另外一种是需要异步加载子节点信息的树节点,该类由Ext.tree.AsyncTreeNode 定义。看下面的代码:
Ext.onReady(function(){
var tree=new Ext.tree.TreePanel({
renderTo:"hello",
root:new Ext.tree.AsyncTreeNode({
text:"根节点"
}),
width:100
});
});
执行程序,点击树中的”根节点”则会一直发现树会尝试加载这个节点的子节点,由这里没有指定树的加载器,所以”根节点”会变成一直处于加载的状态。
B: TreeNode 与AsyncTreeNode 可以同时使用
对于普通的TreeNode 来说,可以通过调用节点的appendChild、removeChild 等方法来往该节点中加入子节点或删除子节点等操作。
TreeNode 与AsyncTreeNode 可以同时使用,比如下面的代码:
Ext.onReady(function(){
var root=new Ext.tree.TreeNode({
id:"root",
text:"树的根"
});
var c1=new Ext.tree.TreeNode({
text:"子节点1"
})
var c2=new Ext.tree.AsyncTreeNode({
text:"子节点2"
});
root.appendChild(c1);
root.appendChild(c2);
var tree=new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:300,
loader:new Ext.tree.TreeLoader({
applyLoader:false,
url:"treedata.js"
})
});
});
treedata.js 中的内容仍然是:
[{
id: 1,
text: '子节点'
}]
另外要在树以外的程序中得到当前选择的节点,可以通过TreePanel 的getSelectionModel 方法来获得,该方法默认返回的是Ext.tree.DefaultSelectionModel 对象,DefaultSelectionModel 的getSelectedNode 方法返回当前选择的树节点。比如要得到树tree 中当前选择节点,代码如下:
tree.getSelectionModel().getSelectedNode()
对于ExtJS 中的树来说,树加载器TreeLoader 是一个比较关键的部件,树加载器由
Ext.tree.TreeLoader 类定义,只有AsyncTreeNode 才会使用TreeLoader。看下面的代码:
Ext.onReady(function(){
var loader=new Ext.tree.TreeLoader({
url:"treedata.js"
});
var root=new Ext.tree.AsyncTreeNode({
id:"root",
text:"根节点",
loader:loader});
var tree=new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:100
});
});
首先我们使用Ext.tree.TreeLoader 来初始化了一个TreeLoader 对象,构造函数中的配置参数url 表示获得树节点信息的url 。然后在初始化根节点的时候我们使用的是AsyncTreeNode,在该节点中指定该节点的laoder 为前面定义的loader。执行这段程序,在点击”根节点”时,会从服务器端指定root 节点的子节点信息。
TreeLoader 严格来说是针对树的节点来定义的,可以给树中的每一个节点定义不同的TreeLoader,默认情况下,如果一个AsyncTreeNode 节点在准备加载子节点的时候,如果该节点上没有定义loader,则会使用TreePanel 中定义的loader 作为加载器。因此,我们可以直接在TreePanel 上面指定loader 属性,这样就不需要给每一个节点指定具体的TreeLoader了。