Ext树形结构——TreePanel

Ext 专栏收录该内容
42 篇文章 0 订阅

创建一个树

树控件由Ext.tree.TreePanel类定义,控件名称为treepanel,继承自Panel面板。

要实现一棵树也很简单:

1.创建一个TreePanel

2.为TreePanel设置一个根结点(RootNode)

3.添加子节点(TreeNode)到根几点。

示例:

Ext.BLANK_IMAGE_URL = '../../resources/images/default/s.gif';

 

Ext.onReady(function() {

var treepanel = new Ext.tree.TreePanel({

el:"tree",

width:300,

autoHeight:true, //如果不明确指定高度,需要将autoHeight设置为TRUE,使其自动计算高度,否则显示不了(高度为0

frame:true,

title:"My Tree",

useArrows:true,

autoScroll:true,

animate:true,

enableDD:true,

containerScroll: true,

rootVisible: true// 根几点可见,默认TRUE

});

 

var rootNode = 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:"根下的第一个树干下的第1个叶子"

});

var node4 = new Ext.tree.TreeNode({

text:"根下的第一个树干下的第2个叶子"

});

var node5 = new Ext.tree.TreeNode({

text:"根下的第2个树干"

});

var node6 = new Ext.tree.TreeNode({

text:"根下的第2个树干"

});

 

treepanel.setRootNode(rootNode);

node1.appendChild(node3);

node1.appendChild(node4);

rootNode.appendChild(node1);

rootNode.appendChild(node2);

node5.appendChild(node6);

rootNode.appendChild(node5);

treepanel.render();

 

Ext.get("expandAllNode").on("click",function() {

//1.展开所有节点,2.动画展开

rootNode.expand(true,true);

});

});

 

HTML

<div id="tree">

<inputtype="button" id="expandAllNode"value="展开所有节点">

</div>

 

TreePanel上放置了一个按钮,单击按钮以动画形式展开所有节点。

效果:


不管是根节点还是子节点,都是TreeNode。如果一个节点有子节点,那它就是一个树干(文件夹图标),如果没有子节点那就是一个叶子节点(文件图标)。

 

 

22.2使用TreeLoader加载数据生成树

Ext.tree.TreeLoader可以利用后台数据动态生成一棵树,我们只需要提供数据,TreeLoader完成转换和装配节点的操作。

示例:

// 使用Ajax读取数据生成树

var treepanel2= new Ext.tree.TreePanel({

renderTo:"tree2",

width:500,

autoHeight:true, //如果不明确指定高度,需要将autoHeight设置为TRUE,使其自动计算高度,否则显示不了(高度为0

frame:true,

title:"AsyncTreeNode",

useArrows:true,

autoScroll:true,

animate:true,

enableDD:true,

containerScroll: true,

rootVisible: true, // 根几点可见,默认TRUE

loader:new Ext.tree.TreeLoader({

dataUrl:"./asyncTreeNode.txt"// 从这里获取数据生成数节点

}),

root: {

text:"Country", // 根节点

nodeType: 'async'// 异步(等同于Ext.tree.AsyncTreeNode)

}

});

 

./asyncTreeNode.txt内容:

[{

id:2,

text:"China",

children:[

{

id:2001,

text:"Guangdong",

children:[

{

id:20011,

text:"Shenzhen",

children:[

{id:200111,text:"Nanshan",leaf:true},

{id:200112,text:"Futian",leaf:true},

{id:200113,text:"Baoan",leaf:true},

{id:200114,text:"Luohu",leaf:true}

]

}

]

}

]

},

{

id:3,

text:"America",

children:[

{id:3001,text:"NewYork",leaf:true}

]

}]

 

效果:

不过,如果远程获取的数据包含中文则页面显示乱码。

TreeLoader在生成节点时会判断数据中的leaf属性,如果为true,则会生成TreeNode,否则生成AsyncTreeNode。TreeNode是不会自动去Ajax取值的。

 

 

22.3读取本地Json数据生成树

读取本地Json数据是TreeLoader的另类方法,可以读取本地JavaScript中的Json数据生成树。

1.为TreePanel设置一个参数为空的TreeLoader

2.设置根节点,并设置children属性。

示例:

var treepanel3= new Ext.tree.TreePanel({

renderTo:"tree3",

width:500,

autoHeight:true,

frame:true,

title:"读取本地Json数据",

useArrows:true,

autoScroll:true,

animate:true,

enableDD:true,

containerScroll: true,

rootVisible: true, // 根几点可见,默认TRUE

loader:new Ext.tree.TreeLoader(),

root: {

text:"国家", // 根节点

children:[

{text:"中国",children:[

{text:"广东省",leaf:true},

{text:"湖南省",leaf:true},

{text:"湖北省",leaf:true}

]},

{text:"美国",leaf:true}

],

nodeType: 'async'// 异步(等同于Ext.tree.AsyncTreeNode)

}

});

 

效果:


注意:

1.一定要设置TreeLoader,否则会一直处于读取状态

2.必须是AsyncTreeNode,否则无法生成子节点

3.叶子节点要加上leaf:true,否则也会一直处于读取状态。

 

 

22.4使用Servlet提供数据

将根结点的id设置为0,后台根据id判断当前正在展开的 节点是哪个,然后提供相应的子节点的数据。

Js

vartreepanel4 = newExt.tree.TreePanel({

renderTo:"tree4",

width:500,

autoHeight:true,

frame:true,

title:"读取Servlet数据",

useArrows:true,

autoScroll:true,

animate:true,

enableDD:true,

containerScroll: true,

rootVisible: true, // 根几点可见,默认TRUE

// auto create TreeLoader

dataUrl:"/myExt2.3/TreePanelServlet",

root: {

id:"0",

text:"全部好友", // 根节点

nodeType: 'async'// 异步(等同于Ext.tree.AsyncTreeNode)

}

});

 

// 自动展开根节点

treepanel4.getRootNode().expand();

 

Servlet

request.setCharacterEncoding("utf-8");

response.setCharacterEncoding("utf-8");

 

// 获取单击的节点的Id

Stringnode = request.getParameter("node");

System.out.println(node);

Stringjson = "";

 

if ("0".equals(node)) { // 全部分组

json += "[{id:'1',text:'我的好友'},{id:'2',text:'我的同学'},{id:'3',text:'陌生人'}]";

}

elseif ("1".equals(node)) { // 我的好友

json += "[{id:'11',text:'张三',leaf:true},{id:'12',text:'里斯',leaf:true},{id:'13',text:'王五',leaf:true}]";

}

elseif ("2".equals(node)) { // 我的同学

json += "[{id:'21',text:'周瑜',leaf:true},{id:'22',text:'黄盖',leaf:true},{id:'23',text:'诸葛亮',leaf:true}]";

}

 

response.getWriter().print(json);

System.out.println(json);

 

效果:


我们使用treepanel4.getRootNode().expand();展开根结点的子节点,看到的就是上面的样子。

展开所有分组后的效果:

 

22.5树的事件

我们主要看看这几种事件:展开(expandnode)、折叠(collapsenode)、单击(click)、双击dblclick)。

treepanel4.on("expandnode",function(node) {

Ext.log(node.id + "展开了");

});

treepanel4.on("collapsenode",function(node) {

Ext.log(node.id + "被折叠了");

});

treepanel4.on("click",function(node,e) {

Ext.log("单击" + node.id);

});

treepanel4.on("dbclick",function(node,e) {

Ext.log("双击" + node.id);

});

 

引入ext-all-debug.js,使用ext.log()看日志。

 

效果:

 

22.6右键菜单

添加右键菜单也很简单,2步搞定。

1. 定义右键菜单。

2. TreePanel添加右键菜单事件。

 

示例:

// 添加右键菜单

varcontextMenu = newExt.menu.Menu({

id:"treeContextMenu",

items:[

{

text:"查看",

handler:function() {

Ext.Msg.alert("...","你单击了" + cth.node.id);

}

}

]

});

 

var cth =function() {};

 

treepanel4.on("contextmenu",function(node,e) {

e.preventDefault(); // 阻止弹出默认右键菜单

node.select(); // 选中节点

// 赋给cth,这样在菜单事件中就可以使用了。

cth.node = node;

contextMenu.showAt(e.getXY());

});

 

效果:


单击查看菜单,弹出节点Id

22.6修改节点的默认图标

第一种方式:修改ext-all.css中关于tree的定义。

第二种方式:在TreeNode中设置icon属性,如:

root: {

id:"0",

icon:"./imgs/img.png",

text:"全部好友", // 根节点

nodeType: 'async'// 异步(等同于Ext.tree.AsyncTreeNode)

}

当然,这个修改的是根节点的图标。

 

第三种方式:自定义CSS,并在TreeNodeiconCls属性中指定。

可以参照ext-all.css中的定义来自定义css

 

 

22.7给节点增加提示信息

给节点增加提示信息很简单,只需要在TreeNode中增加qtip属性就可以了。

如:

[{id:'21',text:'周瑜',leaf:true,qtip:'三国时期的人物'},{id:'22',text:'黄盖',leaf:true},{id:'23',text:'诸葛亮',leaf:true}]

在节点21上增加了qtip,那么当鼠标放到这个节点上的时候就会提示qtip的内容,当然,前提还是要Ext.QuickTips.init();

效果:

 

 

22.8为节点设置超链接

在节点中增加hrefhrefTarget属性即可。

如:

[{id:'21',text:'周瑜',leaf:true,qtip:'三国时期的人物',href:'./autoload_form_data.html',hrefTarget:'_blank'},{id:'22',text:'黄盖',leaf:true},{id:'23',text:'诸葛亮',leaf:true}]

在节点21上增加了hrefhrefTarget属性,当点击这个节点时弹出新窗口autoload_form_data.html

 

2个参数的意思就很明显了,href:要访问的地址。hrefTarget:决定如何打开新窗口。

我们将hrefTarget设置为_self,那么就在当前窗口打开。

 

 

 

22.9编辑节点名称

只需要定义一个TreeEditor,将TreePanel放进去即可。

示例:

// 编辑节点名称

vartreeEditor = newExt.tree.TreeEditor(treepanel4,{

allowBlank:false

});

 

treeEditor.on("beforestartedit",function(editor,tree,value){

// 只允许编辑叶子节点

return editor.editNode.isLeaf();

});

 

treeEditor.on("complete",function(editor,value,startValue){

Ext.Msg.show({

title:"提示",

msg:"旧值:"+startValue+"节点新值:" + value

});

});

 

效果:

 

22.10树形的拖放

22.10.1树形的拖放

如果想让树形的节点可以自由拖放,在构建TreePanel时将enableDD设置为TRUE就可。

 

Ext提供了3种形式的拖放:

1. Append:放下去的节点会成为目标节点的子节点,形成父子关系,标记是一个绿色的加好图标。


2. above:放下去的节点与目标节点是兄弟关系,放下去的节点在前。标记是一个箭头2个短横线。


3. below:放下去的节点与目标节点是兄弟关系,放下去的节点在后。标记与above相反。


 

22.10.2叶子节点不能append

默认情况下,叶子节点是不能append的。主要是通过判断目标节点的leaf属性判断,如果leaf属性为TRUE,则说明为叶子节点,就不能append;如果为FALSE,就可以append

那怎样让叶子节点也能append呢?

我们在nodedragover事件中处理,将target.leaf设置为TRUE就可以了。

代码:

// 在将一个节点拖拽到另一个节点上时触发。

// 默认情况下,叶子节点是不能直接append,判断能不能append就是看leaf属性是否为TRUE

// 如果为TRUE,说明为叶子节点,就不能append;反之就可以append.

// 这里处理:如果目标是叶子节点,则将leaf设置为FALSE,这样就可以在叶子节点append,这样就可以形成树干(文件夹)。

treepanel4.on("nodedragover",function(dragOverEvent){

var target = dragOverEvent.target;

if (target.leaf) {

target.leaf = false;

}

returntrue;

});

这样形成的效果就是,拖放后形成树干(文件夹)。

我现在将张三拖放到王五上面,看看最终形成的效果:


张三成了王五的子节点。(本来都是叶子节点的,但是现在拖拽形成了树干节点)

 

 

22.10.3判断拖放目标

在拖放完成后会触发nodedrop事件,

看看nodedrop事件的说明:

nodedrop : (ObjectdropEvent)

Fires after a DDobject is dropped on a node in this tree. The dropEvent passed to handlers hasthe following properties:

  • tree - The TreePanel
  • target - The node being targeted for the drop
  • data - The drag data from the drag source
  • point - The point of the drop - append, above or below
  • source - The drag source
  • rawEvent - Raw mouse event
  • dropNode - Dropped node(s).

tree - TheTreePanel

target - The nodebeing targeted for the drop

data - The dragdata from the drag source

point - The pointof the drop - append, above or below

source - The dragsource

rawEvent - Rawmouse event

dropNode - Droppednode(s).

Fires after a DD object is dropped on a node in this tree. The dropEventpassed to handlers has the following properties:

  • tree - The TreePanel
  • target - The node being targeted for the drop
  • data - The drag data from the drag source
  • point - The point of the drop - append, above or below
  • source - The drag source
  • rawEvent - Raw mouse event
  • dropNode - Dropped node(s).

odropEvent : Object

 

Listeners will be called with the following arguments:

dropEvent :Object

 

可以看到,有一个参数,携带有这些属性:tree,target,data,point,source,rawEvent,dropNode,使用这些属性,我们就知道拖放源,拖放目标,拖放方式等等。

 

示例:

// 判断拖放的目标

treepanel4.on("nodedrop",function(e) {

Ext.Msg.show({

title:"提示",

msg:e.dropNode.text + "被拖放到" + e.target.text+"上了,拖放方式为:" + e.point

});

});

 

效果:

 

我们将被拖放的节点ID,拖放的目标节点Id等参数传递给后台,后台就可以修改数据库了。

这里作为演示,只是使用Ajax与后台通信,将参数传递给后台并返回提示信息。

 

示例:

// 判断拖放的目标

treepanel4.on("nodedrop",function(e) {

/*Ext.Msg.show({

title:"提示",

msg:e.dropNode.text + "被拖放到" + e.target.text+"上了,拖放方式为:" + e.point

});*/

 

var item = {

dropNode:e.dropNode.id, // 被拖放的节点

target:e.target.id, // 目标节点

point:e.point // 拖放方式

};

 

Ext.Ajax.request({

method:"post",

url:"./jsp/tree.jsp",

success:function(r) {

var msg = r.responseText;

Ext.Msg.show({

title:"提示",

msg:msg

});

},

failure:function(r) {

Ext.Msg.show({

title:"错误",

msg:"网络不可达!",

buttons:Ext.Msg.OK,

icon:Ext.MessageBox.ERROR

});

},

params:item

});

});

 

结果:

 

22.10.4树之间的拖放

TreePanel中有参数设置只允许Drag和只允许Drop,以及同时允许DragDrop,默认情况下设置enableDD即表示既可以Drag又可以Drop

 

下面的例子中,TreePanel1只允许DragTreePanel2只允许Drop,即只允许从TreePanel1拖放到TreePanel2

 

示例:

Js

// 树之间的拖放。——Drag

var tree1 = new Ext.tree.TreePanel({

title:"TreePanel1",

width:500,

autoHeight:true,

frame:true,

enableDrag:true, // 只允许Drag

containerScroll:true,

dataUrl:"./data/tree1.txt",

root:{

id:1000,

text:"Root Node(TreePanel1)",

nodeType:"async"

},

renderTo:"dragtree1",

autoScroll:true

});

 

// 展开所有节点

tree1.expandAll();

 

// 树之间的拖放。——Drop

var tree2 = new Ext.tree.TreePanel({

title:"TreePanel2",

width:500,

frame:true,

enableDrop:true, // 只允许Drop

containerScroll:true,

autoHeight:true,

dataUrl:"./data/tree2.txt",

root:{

id:1000,

text:"Root Node(TreePanel2)",

nodeType:"async"

},

renderTo:"droptree1",

autoScroll:true

});

 

// 展开所有节点

tree2.expandAll();

 

HTML

这个Table的作用就是让TreePanel1TreePanel2可以在一水平线上。

<table>

<tr>

<td>

<span>Drag Tree</span>

<br>

<hr>

<div id="dragtree1">

 

</div>

</td>

<td>

<span>Drop Tree</span>

<br>

<hr>

<div id="droptree1">

 

</div>

</td>

</tr>

</table>

 

./data/tree1.txt:

 

{id:10001,text:"Node1(TreePanel1)",leaf:true},

{id:10002,text:"Node2(TreePanel1)",children:[

{id:100021,text:"Node21(TreePanel1)",leaf:true},

{id:100022,text:"Node22(TreePanel1)",leaf:true},

{id:100023,text:"Node23(TreePanel1)",leaf:true},

{id:100024,text:"Node24(TreePanel1)",leaf:true},

{id:100025,text:"Node25(TreePanel1)",leaf:true}

]},

{id:10003,text:"Node3(TreePanel1)",leaf:true}

]

 

./data/tree2.txt:

 

{id:10001,text:"Node1(TreePanel2)",leaf:true},

{id:10002,text:"Node2(TreePanel2)",children:[

{id:100021,text:"Node21(TreePanel2)",leaf:true},

{id:100022,text:"Node22(TreePanel2)",leaf:true},

{id:100023,text:"Node23(TreePanel2)",leaf:true},

{id:100024,text:"Node24(TreePanel2)",leaf:true},

{id:100025,text:"Node25(TreePanel2)",leaf:true}

]},

{id:10003,text:"Node3(TreePanel2)",leaf:true}

]

 

效果:


这是将TreePanel1Node22拖放到TreePanel2的效果。

 

 

22.11过滤器——Ext.tree.TreeFilter

如果树的节点太多,一个个找起来就很麻烦,能不能过滤掉不需要的节点呢?答案是肯定的。使用Ext.tree.TreeFitler即可实现。

 

Ext.tree.TreeFilter常用参数:

ClearBlank:如果查询的字符串为空,则执行clear();

autoClear:每次过滤前先执行clear(),否则会在上次执行结果上执行查询

 

方法主要是:filter()filterBy():

filter( String/RegExp value, [Stringattr], [TreeNode startNode] ) : void

Filter the data by a specificattribute.

Parameters:

value : String/RegExp

Either string that the attributevalue should start with or a RegExp to test against the attribute

attr : String

(optional) The attribute passed inyour node's attributes collection. Defaults to "text".

startNode : TreeNode

(optional) The node to start thefilter at.

String/RegExp:要搜索的字符串或正则表达式

String attr:与节点的哪个属性匹配,默认text

startNode:从哪个节点开始过滤。

 

filterBy( Function fn, [Objectscope] ) : void

Filter by afunction. The passed function will be called with each node in the tree (or fromthe startNode). If a node isfiltered, its children are also filtered.If anode is filtered, its children are also filtered.

Filter by afunction. The passed function will be called with each node in the tree (orfrom the startNode). If the function returns true, the node is kept otherwiseit is filtered. If a node is filtered, its children are also filtered.

Parameters:

 

fn : Function

The filter function

scope : Object

(optional) Thescope of the function (defaults to the current node)

 

Filter()filterBy()函数都会遍历每个节点(如果指定startNode,则从此节点开始)。

 

示例:

// 给树增加过滤器

var tree3 = new Ext.tree.TreePanel({

title:"TreePanel2",

width:500,

height:300,

frame:true,

enableDrop:true, // 只允许Drop

containerScroll:true,

dataUrl:"./data/tree3.txt",

root:{

id:1000,

text:"Root Node(TreePanel3)",

nodeType:"async"

},

el:"treefilter",

autoScroll:true

});

 

// 我在Div中增加了一个input,如果使用renderTo就会显示到TreePanel外,使用render()就可以显示到一个panel

tree3.render();

// 展开所有节点

tree3.expandAll();

 

// 创建一个树形过滤器

var filter = new Ext.tree.TreeFilter(tree3, {

clearBlank: true, // 如果输入过滤条件为空,则执行clear()函数。

autoClear: true// 每次执行过滤前,自动执行clear()函数,否则会从上次过滤的结果上执行查询。

});

 

var hiddenPkgs = []; // 保存没有过滤掉的节点

 

// 为输入框添加keyup事件,键入内容执行搜索

Ext.get("treefilterField").on("keyup",function(e) {

// 过滤条件

var text = this.dom.value;

 

// 没被过滤掉的节点就是符合条件的节点

// 遍历这些节点,显示它们。

Ext.each(hiddenPkgs, function(n){

n.ui.show();

});

 

// 未输入,则执行clear(),显示所有节点。

if(!text){

filter.clear();

return;

}

 

// 展开所有节点(未被过滤掉的节点)

tree3.expandAll();

 

// 根据输入构建正则表达式,过滤不区分大小写。

var re = new RegExp('^' + Ext.escapeRe(text), 'i');

 

// 使用filterBy()函数过滤

// 遍历TreePanel中每一个节点,如果不是叶子节点或符合过滤条件都过滤掉。

filter.filterBy(function(n){

return !n.isLeaf() || re.test(n.text);

});

 

// hide empty packages that weren'tfiltered

hiddenPkgs = [];

 

// 从根节点开始遍历其下的所有子节点,没有过滤掉的节点放入hiddenPkgs

tree3.root.cascade(function(n){

if(!n.isLeaf() &&n.ui.ctNode.offsetHeight < 3){

n.ui.hide();

hiddenPkgs.push(n);

}

});

});

 

 

效果:


这是页面加载后展开所有节点的结果。

 

在输入框键入node2


可以看到,显示的都是以node2开头的节点(不区分大小写)。

 

 

 

22.12对树进行排序

Ext.tree.TreeSorter是专门用来对树进行排序的,使用它可以轻松实现排序。

几个重要的参数:

folderSort:是否让叶子节点排在非叶子节点之后,默认FALSE

caseSensitive:排序时是否区分大小写,默认FALSE。

Dir:排序方式,ASC/DESC。

leafAttr:判断叶子节点的标志,默认是leaf,如果节点中存在leaf:true,则认为是叶子节点。
property:根据哪个属性进行排序,默认text。

 

示例:

// 排序、

var treesorter= new Ext.tree.TreeSorter(treepanel4,{

folderSort:true// 让所有叶子节点排在非叶子节点后面

});

 

Servlet返回的数据

[{id:'00',text:'aaa',leaf:true},{id:'1',text:'我的好友',qtip:'我的好友'},{id:'2',text:'我的同学'},{id:'3',text:'陌生人',leaf:true}]

按道理来讲,aaa应该在我的好友前,但我们使用TreeSorter进行排序后,就放到了后面,因为它是叶子节点。

 

22.13对树增加复选框

很多时候我们需要用到带checkbox的树,实现带checkbox的树也很简单,只需要在返回的数据中加上checked:false/true就可以了。

 

不过,如果是这样的话,选中父节点,下面的子节点是不会被选中的。那要怎样在选中父节点后,自动选中它下面的子节点呢?

TreePanel有一个checkchange事件,当你选择或取消选中checkbox时触发。携带2个参数,Node:当前执行选中/取消选中的节点。

Checked:true(当前选中此节点)/false(当前取消选中此节点)

 

那如何知道选中了哪些节点呢?这个倒是容易,TreeNode.ui.isChecked()用来判断某个节点的选中状态。那么我们使用TreeNode.cascade()从根节点开始遍历,判断是否选中就可以了。

 

示例:

// 选中父节点时自动选中子节点

tree3.on('checkchange', function(node, checked) {

// 展开节点

node.expand();

// 改变节点的选中状态

node.attributes.checked= checked;

 

// 遍历所有子节点,改变子节点的选中状态

node.eachChild(function(child) {

child.ui.toggleCheck(checked);

child.attributes.checked= checked;

// 触发子节点的checkchange事件,改变子节点选中状态(递归)

child.fireEvent('checkchange', child, checked);

});

}, tree3);

 

// 获取选中的节点

Ext.get("showCheckedNode").on("click",function() {

var checkedNodesText = "";

 

// 从根结点开始遍历所有子节点,获取选中的节点

tree3.root.cascade(function(node) {

if (node.ui.isChecked()) {

checkedNodesText +=node.text + ",";

}

});

checkedNodesText =checkedNodesText.substring(0,checkedNodesText.length-1);

 

Ext.Msg.show({

title:"提示",

msg:"选中的节点:" + checkedNodesText,

buttons:Ext.Msg.OK,

icon:Ext.Msg.INFO

});

});

效果:

 

 

22.13表格与树形结合——Ext.tree.ColumnTree

在某些情形中,我们需要实现在表格中分级显示的功能,它与分组表格Ext.grid.GroupingGrid很相似,这二者都能对不同分类数据进行折叠和展开。通过继承Ext.tree.TreePanelExt.tree.TreeNodeUI实现表格与树形结合的效果:

如图:


这是extexamples/tree/column-tree.html的效果。

 

为了使用ext.tree.TreeNodeUI,需要将extexamples/tree/column-tree.cssColumnNodeUI.js引入。

引入后就可以使用Ext.tree.ColumnTree创建表格形式的树形。

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:程序猿惹谁了 设计师:我叫白小胖 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值