树控件:
树是由根节点、叶子节点、非叶子节点(目录节点)组成的,其中根节点只有一个,叶子节点是终端节点。
ext中节点类型有普通树节点和异步加载节点(用于后台交互)
ext中提供了节点的选择模型:单选(选择一行) 多选(选择多行) 复选(通过复选框选择)
TreePanel用于呈现我们树的面板。TreeNode是树节点,AsyncTreeNode是动态加载树节点(异步树节点)。
既然我们要创建Tree,首先要创建一个根,当然ext中根节点也是节点所以统一用TreeNode进行创建。
TreeNode中text属性表示节点名称,leaf表示节点是否是叶子节点,id节点的唯一标识,href,hreftarget表示连接地址及打开方式,draggable表示拖拽,checked表示在节点前面是否展现复选框,allowChildren,allowDrag是否允许添加子节点,是否允许拖动等等。这里text,id是必须的。
我们创建好根之后,就要创建一个树面板(TreePanel)。
TreePanel中的配置选项包含root属性,根节点。renderto用于渲染的div
<body>
<div id="hello"></div>
</body>
Ext.onReady(function(){
var root = new Ext.tree.TreeNode({
id:"root",
text:"我是根"
});
var tree = new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:200
});
});
这样一颗简单的树就呈现出来了
好像太简单了 我们就想根节点添加一些节点
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:200
});
});
我们发现树的图标发生了改变,可以清晰的看出是否是叶子节点。
我们也可以通过leaf属性进行指定。但是这里我们即便手动定义了leaf:false也是不起作用的因为他下面没有节点。这一点与树的加载方式有关。
如果下面有子节点我们可以强制定义成true
Ext.onReady(function(){
var root = new Ext.tree.TreeNode({
id:"root",
text:"我是根"
});
root.appendChild(new Ext.tree.TreeNode({
id:"c1",
text:"我是子节点",
leaf:false
}));
var c2 = new Ext.tree.TreeNode({
id:"c2",
text:"我是子节点2"
});
c2.appendChild(new Ext.tree.TreeNode({
id:"c21",
text:"我是子节点2的子节点"
}));
root.appendChild(c2);
var tree = new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:200
});
});
Ext.onReady(function(){
var root = new Ext.tree.TreeNode({
id:"root",
text:"我是根"
});
root.appendChild(new Ext.tree.TreeNode({
id:"c1",
text:"我是子节点",
leaf:false
}));
var c2 = new Ext.tree.TreeNode({
id:"c2",
text:"我是子节点2",
leaf:true
});
c2.appendChild(new Ext.tree.TreeNode({
id:"c21",
text:"我是子节点2的子节点"
}));
root.appendChild(c2);
var tree = new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:200
});
});
这里我们需要点击节点前面的+-进行展开收缩,
我们也可以通过直接点击节点区域进行展开或者收缩,这里可以通过TreeNode中的singleClickExpand:boolean
Ext.onReady(function(){
var root = new Ext.tree.TreeNode({
id:"root",
text:"我是根",
singleClickExpand:true
});
root.appendChild(new Ext.tree.TreeNode({
id:"c1",
text:"我是子节点",
leaf:false
}));
var c2 = new Ext.tree.TreeNode({
id:"c2",
text:"我是子节点2"
//leaf:true
});
c2.appendChild(new Ext.tree.TreeNode({
id:"c21",
text:"我是子节点2的子节点"
}));
root.appendChild(c2);
var tree = new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:200
});
});
以上内容简单介绍了一下静态树的应用,下面我们来研究一下异步加载树的应用。
这里我们要用AsyncTreeNode对TreeNode进行替换。
这里我们同样需要一个根,不过这里的根节点我们使用了AsyncTreeNode异步加载树节点。
AsyncTreeNode是继承于TreeNode。loader是他自己对于TreeNode的扩展,同样我们可以按TreeNode的方式进行添加
Ext.onReady(function(){
var root = new Ext.tree.AsyncTreeNode({
id:"root",
text:"异步树的根"
});
root.appendChild(new Ext.tree.TreeNode({
id:"c1",
text:"我是子节点",
leaf:false
}));
var tree = new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:200
});
});
不同的是当我们展开根之后,根节点前的图标显示一直在加载的状态
这是因为他是一个异步的节点,所以一定要有一个加载器进行数据加载来完成他的功能。
这里就用到AsyncTreeNode独有的属性loader:TreeLoader。
我们要指定一个TreeLoader来完成异步加载的数据。
Ext.tree.TreeLoader中的配置选项包括url,dataurl
实际上只需返回一个json字符串就可以了。
[{
id:"c1",
text:"子节点"
},{
id:"c2",
text:"子节点2"
}]
Ext.onReady(function(){
var root = new Ext.tree.AsyncTreeNode({
id:"root",
text:"异步树的根",
loader:new Ext.tree.TreeLoader({
url:"treedata.js"
})
});
root.appendChild(new Ext.tree.TreeNode({
id:"c1",
text:"我是子节点",
leaf:false
}));
var tree = new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:200
});
});
这里的url是现对于引用界面的相对路径
我们可以看到当使用loader之后原
root.appendChild(new Ext.tree.TreeNode({
id:"c1",
text:"我是子节点",
leaf:false
}));
将不起作用。
这里我们发现树竟然展不完,竟然是一个无限循环。
由于我们的json数据中没有指定他是叶子节点,所以当再次点击的时候他又会重新加载,并将数据挂在当前节点下面。
根本原因在于我们将loader放置在root下面,等同于将它放置在treePanel下面
Ext.onReady(function(){
var root = new Ext.tree.AsyncTreeNode({
id:"root",
text:"异步树的根"
});
root.appendChild(new Ext.tree.TreeNode({
id:"c1",
text:"我是子节点",
leaf:false
}));
var tree = new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:200,
loader:new Ext.tree.TreeLoader({
url:"treedata.js"
})
});
});
[{
id:"c1",
text:"子节点",
leaf:true
},{
id:"c2",
text:"子节点2"
}]
实际上loader的放置位置与实际的呈现效果会有一些区别。
这里我们间静态树节点和异步节点结合起来看看
Ext.onReady(function(){
var root = new Ext.tree.TreeNode({
id:"root",
text:"异步树的根"
});
root.appendChild(new Ext.tree.TreeNode({
id:"c1",
text:"我是子节点",
leaf:false
}));
var c2 = new Ext.tree.AsyncTreeNode({
id:"c2",
text:"我是子节点2",
loader:new Ext.tree.TreeLoader({
url:"treedata.js"
})
});
root.appendChild(c2);
var tree = new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:200
});
});
[{
id:"c1",
text:"子节点21",
leaf:true
},{
id:"c2",
text:"子节点22"
}]
我们将root换成静态节点,这样就不存在root展开时的加载问题
总结:我们在使用AsyncTree的时候需要引入加载器,加载器中的返回的数据是json类型的字符串
节点选择模型
我们首先看一下我们的简单树
Ext.onReady(function(){
var root = new Ext.tree.TreeNode({
id:"root",
text:"我是根"
});
root.appendChild(new Ext.tree.TreeNode({
id:"c1",
text:"我是节点1"
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c2",
text:"我是节点2"
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c3",
text:"我是节点3"
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c4",
text:"我是节点4"
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c5",
text:"我是节点5"
}));
var tree = new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:300
});
});
该树不能选择多行(无论是使用shift ctrl都不可以)
在树的选择模型上存在DefaultSelectionModel和MultiSelectionModel两个模型选择器。
TreePanel可以通过getSelectionModel可以获得选择模型。默认使用DefaultSelect
不过可以通过配置选项的selModel来设置选择模型
我们通过一个例子看一下选择模型的使用
Ext.onReady(function(){
var root = new Ext.tree.TreeNode({
id:"root",
text:"我是根"
});
root.appendChild(new Ext.tree.TreeNode({
id:"c1",
text:"我是节点1"
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c2",
text:"我是节点2"
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c3",
text:"我是节点3"
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c4",
text:"我是节点4"
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c5",
text:"我是节点5"
}));
var tree = new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:300,
tbar:[{
text:"查看",
pressed:true,
handler:showSelected
}]
});
function showSelected(){
var node = tree.getSelectionModel().getSelectedNode();
if(node){
alert(node.text);
}
}
});
他将alert出我们所选节点的text属性
我们来看一看如何使用多选的模型选择器
Ext.onReady(function(){
var root = new Ext.tree.TreeNode({
id:"root",
text:"我是多选根"
});
root.appendChild(new Ext.tree.TreeNode({
id:"c1",
text:"我是节点1"
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c2",
text:"我是节点2"
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c3",
text:"我是节点3"
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c4",
text:"我是节点4"
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c5",
text:"我是节点5"
}));
var tree = new Ext.tree.TreePanel({
renderTo:"hello",
title:"多选树模型",
root:root,
width:300,
selModel:new Ext.tree.MultiSelectionModel(),
tbar:[{
text:"查看",
pressed:true,
handler:showSelected
}]
});
function showSelected(){
var nodes = tree.getSelectionModel().getSelectedNodes();
if(nodes && nodes.length){
alert("选择:"+nodes.length+"个");
}
}
});
这里我们可以通过ctrl进行多行选中
我们可以通过TreeNode的checked配置选项设置复选,并且可以通过TreePanel的getChecked()方法得到被选中节点的数组。
Ext.onReady(function(){
var root = new Ext.tree.TreeNode({
id:"root",
text:"我是复选根",
checked:false
});
root.appendChild(new Ext.tree.TreeNode({
id:"c1",
text:"我是节点1",
checked:true
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c2",
text:"我是节点2",
checked:true
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c3",
text:"我是节点3",
checked:true
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c4",
text:"我是节点4",
checked:true
}));
root.appendChild(new Ext.tree.TreeNode({
id:"c5",
text:"我是节点5",
checked:false
}));
var tree = new Ext.tree.TreePanel({
renderTo:"hello",
title:"复选树模型",
root:root,
width:300,
tbar:[{
text:"查看",
pressed:true,
handler:showSelected
}]
});
function showSelected(){
var nodes = tree.getChecked();
if(nodes && nodes.length){
alert("选择:"+nodes.length+"个");
}
}
});