admin管理员组文章数量:1535374
2024年7月11日发(作者:)
第八章 Tree(树)
层级数据是很多开发者所熟知的。“根-枝-叶”的结构是很多用户界面的最基
本的特征。windows的资源管理器中就展示了一个包含子节点、父节点和更深层次节
点的树,以此来展示文件夹和文件的层级关系。允许开发者只通过使用几行代
码就展示出这样的层级数据,并且提供了大量的简单的配置来适应更广泛的需求。
虽然ExtJS默认的tree节点是file和folder图标样式,但是它不会仅仅将树局限
于文件系统这一概念里。每一项的图标和文字,或者树中的节点,都可以根据动态或
者静态的数据来改变——不需要自己写代码。想想,我们如果希望建立一个用户组,
为每个用户展示它们自己的图标;又或者希望展示一画廊的图片并且在图标中预览这
些图片。ExtJS可以帮助我们实现这些愿望,而且十分简单。
种植未来:
(作者使用培育植物的过程形象化地比喻建立tree的过程)
ExtJS的tree不会关心你显示什么样的数据,因为它可以随心所欲地处理任何你
碰到情况。数据可以实现就加载好,又或者从逻辑上进行分割。你可以直接在tree中
编辑数据,改变标签和位置,或者你可以修改整棵树的样子以及每个节点的外观,一
切都为了用户体验。
ExtJS的tree是从Component模型上建立起来的。Component是真个ExtJS框架
的基础。也就是说,开发者从熟悉的Component的系统中获得了便利,因为用户能偶
得到一种统一的和集成的体验效果。你同样可以保证tree和应用中的其他组件天衣无
缝地工作在一起。
从小种子开始:
在这章里,你可以看到如何使用很少的代码建立一棵树。我们还将讨论利用唯
一的数据结构来产生一个tree,以及如何使用数据可以让你操控重要的配置项。ExtJS
树提供了很多高级支持,例如排序、拖拽等。但是,如果你想要真的定制一棵,我们
还需要探索如何重写或者扩展configure options(配置项目)、methods(方法)、events(事
件)的方法。
tree是通过实例化nel类来建立的,它包含了很多
des的节点类。这两个类是ExtJS树的核心,也是我们这章讨论的主题。
但是,还有很多其他先关的类需要介绍,我们现在列出包中的全部条目:
AsyncTreeNode
DefaultSelectionModel
MultiSelectionModel
RootTreeNodeUI
TreeDragZone
允许子节点异步加载的节点
标准的TreePanel的单选模式
允许多选节点的选择模式
作为TreePanel根的特殊的TreeNode
为TreeNode的抓起提供支持
TreeDropZone
TreeEditor
TreeFilter
TreeLoader
TreeNode
TreeNodeUI
TreePanel
TreeSorter
为TreeNode的放下提供支持
允许节点标签被编辑
对TreePanel中子节点的过滤进行支持
从指定的URL生成TreePanel
在TreePanel中显示节点的最主要的类
为TreeNode提供最基本的界面
树状结构显示数据——最主要的树类
支持TreePanel中节点的排序
天啊!幸运的是,你不用同时全部使用它们。TreeNode和TreePanel提供了最
基础的东西,其它的类是用来提供额外功能的。我们将一个一个对其介绍,讨论如何
使用它们并且展示几个练习示例。
我们的第一个幼苗:
现在,你可能还在思考ExtJS树带来的各种可能性,想亲手去干。尽管
类包含了丰富的功能,但是你只需要几行代码就能让一切跑起来。
在接下来的例子中,我们假设你有一个准备好的空白HTML页面,包含了所有
ExtJS所需要的引用。大部分的代码都基于以前的章节,好让我们抓住重点,你要孤立
地看待它们。最好的方式是吧JS分别放在各个文件中并把代码放在y函数
中。但是,你依然可以根据你自己的编码风格来处理。
准备好土地:
首先我们需要建立
置为我们想要的tree的大小:
tree的JS代码可以分为三部分。首先,我们需要确定tree展现的方式。
ader类提供了这样的功能,现在我们采用最简单的办法来使用它:
var treeLoader = new ader({
});
dataUrl配置项说明了提供产生树所需要的JSON数据的脚本存在的位置。我现
在不想讨论JSON的具体结构,让我们先保留这个问题。
dataUrl:'localhost/'
每个tree都需要一个根节点,它扮演了所有后裔的终极祖先的角色。为了建立
root node(根节点),我们使用reeNode类:
var rootNode = new reeNode({
});
之所以使用AsyncTreeNode而不是TreeNode,是因为我们需要从服务器端获得
节点,并且一层一层地去加载而不是一次性加载。
N:AsyncTreeNode使用AJAX来保证用户不用花太多时间等待数据加载以及首
次节点的渲染。
最后,我们建立tree本身,利用nel类:
var tree = new nel({
});
只需要把root node和TreeLoader放在配置中,再加上决定TreePanel渲染位置
的renderTo配置,就可以显示tree了。
再次提醒,你一定要记住把这些代码放在y中,以此确定DOM在代
码执行前已经准备好了。
renderTo:'treecontainer',
loader: treeLoader,
root: rootNode
text: 'Root'
tree(树)离开data(数据)生长不了:
我们看到,只需要十一行数据就可以显示如下的用户界面:
我猜这还不够,但是这十一行代码提供了大量的功能。利用异步远程加载子节
点,我们获得了统一的交互界面和体验。并不只是这么简单,因为我们将要介绍Ext
树的最重要的部分——data(数据)。
JSON:
标准的TreeLoader支持以一种特定的格式支持JSON数据——包含node定义的
数组,如下所示:
[
]
text属性代表了tree里node的标签文本。id属性用来唯一标识一个node,并
且将被用来决定选中和展开哪个节点。利用id属性我们可以使得TreePanel中高级功
能的实现变的简单,这在之后会介绍到。children属性是可选的。leaf属性是被用来判
断是否为叶子节点。在tree中leaf节点不能被展开,也不会有节点前卖弄的加号图
标。
{ id: '1', text: 'No Children', leaf: true },
{ id: '2', text: 'Has Children',
}
children: [{
}]
id: '3',
text: 'Youngster',
leaf: true
ID简介:
默认来说,TreeNode会被分配一个自动产生的ID,说明id配置可有可无。这
个自动产生的id是一个字符串,形式如:ynode-xx,xx代表数字。id可以被用来获得
一个你之前引用的节点。但是,你很可能自己分配id。当你异步加载节点的时候,服
务器脚本需要准确知道那个节点被点击从而传回其子节点数据。通过设置id,你可以
发现在服务器端匹配节点变得很简单。
额外的数据:
虽然id、text和leaf属性十分常用,但是JSON的用途不只局限于此。事实上,
任何TreeNode的配置都可以被JSON初始化,这是我们探索tree的高级功能的一个小
技巧。你可以添加应用需要的特定的数据——例如也许你的节点代表了产品并且你希
望它们包含价格信息。任何属性都可以以TreeNode配置项的方式组织起来,并且包含
在TreeNode的attributes属性之中。(也就是说,TreeNode本身没有的属性会被组织
在attributes属性之中)。
XML:
XML不是直接被tree支持的。但是你可以利用ExtJS的数据支持来让XML也能
被读取。通常,使用JSON会让一切变得简单,虽然一些程序会使用XML传送数据。
所以它值得我们讨论一下。
我们可以使用oxy来获得数据,但是我们需要在读取数据的时候
把XML转换一下:
var xmltree = new nel({el: 'treeContainer'});
var proxy = new oxy({url:
}
}, function(){ (); });
我们建立了一个新的TreePanel和HttpProxy,并且指定在proxy加载时使用
来处理进入的XML数据。我们接下来会告诉reader把XML传递到
parseXmlAdnCreateNodes。在这个函数中,你可以根据XML数据来建立根节点和子节
点,我们向它直接传递了一个XML文档。
JS完全能够处理XML数据,虽然你可能更习惯于转换XHTML文档中DOM的方
式。通过读取XML文档你可以建立和使用textnodes(文本节点)。因为在这种方式
里,你需要访问原始的XML节点,你可以完全地控制由此产生的tree和相应的树节
点。
'localhost:81/ext/'});
(null, {
read: function(xmlDocument) {
parseXmlAndCreateNodes(xmlDocument);
照料你的树:
我们将讨论使你的tree更加实用的功能。拖拽、排序和编辑节点。
拖拽:
当你使用TreePanel的时候,ExtJS管理着由拖拽产生的用户界面。只要添加
enableDD: true配置到tree里,这时你可以通过拖拽重新组织树的节点,当显示绿色加
号的时候,代表你可以向目标防止该节点。
N:TreePanel不仅仅只会“照顾”它们自己的节点,当你的界面中有两棵树的
时候,他们的节点可以在树之间相互拖拽。
但这还没有完。当你刷新你的页面,所有的节点又回到原位。因为TreePanel
不会自动知道你是否需要保存改动,为了实现保存,我们需要借助一些事件
(event)。
TreePanel的beforemovenode事件在拖放的时候松开鼠标,但是在TreePanel反
映变化前这一时间点触发。我们可以添加如下代码来告诉服务器移动节点这一事件:
('beforemovenode', function(tree, node, oldParent, newParent, index) {
});
我们为beforemovenode事件添加了事件处理函数。这个函数在调用的时候向
其传递了几个有用的参数:
1, tree:该事件所发生的TreePanel;
t({
});
url: 'localhost/',
params: {
}
nodeid: ,
newparentid: ,
oldparentid: ,
dropindex: index
2, node:被移动的节点;
3, oldParent:被移动节点之前的父节点;
4, newParent:被移动节点的新的父节点;
5, index:移动目的的序号。
我们利用以上这些来形成AJAX对服务器发请求时传递的参数。这样,你可以
获得tree现在的任何信息和状态,你的服务端脚本可据此以完成任何你需要的动作。
在某些桩抗下,你可能需要取消拖放节点。当你在beforemovenode函数中出
现了逻辑上的错误,你需要还原改动。如果你不发送AJAX请求,可以直接在函数的最
后返回false即可,相应的动作将被取消。但是如果你采用了AJAX,就困难了许多,因
为XMLHttpRequest是异步发生的,而且这个事件函数会执行一些默认的动作,其中就
包括允许节点移动。
即然这样,你需要确定你为AJAX提供了failure函数的配置,向这个函数传递
足够的参数,好让树还原到以前的状态。因为beforemovenode通过默认传递的参数提
供了大量的信息,所以你可以传递必须的数据来对产生的错误进行管理。
排序:
我们可以通过一种灵活的方法为TreePanel排序——TreeSorter。在先前代码的
基础上,我们可以建立一个如下的TreeSorter:
new rter(tree, {
});
因为TreeSorter采用了几个约定——leaf节点由leaf属性标明并且标签文本在
text属性里说明——我们可以很容易地按字母进行排序。dir属性g奥素我们
TreeSorter是按照升序还是降序进行排序的。folderSort为true(默认为false)表明叶
子节点需要在非叶子节点下进行排序,也就是说,整个树每层都要进行排序。
如果你的数据不仅仅是简单的文本,我们可以通过sortType配置项自定义排
序。sortType的值是一个函数,而且只向其传递一个参数:a TreeNode。
sortType允许你为TreeNode新加自定义属性——这个属性可能是服务器传来的
和业务相关的信息——并且把它转化成Ext可以排序的格式,换句话说,也就是转化
为标准的JS类型,如整型、字符串、日期。sortType一般用在原有的数据格式不能或
者不方便做搜索以及排序的时候——从服务器返回的数据可能会被用于不同的目的,
我们可以把日期转化为标准的格式——从US样式的MM/DD/YY转化为YYYYMMDD样
式(以便排序)——或者我们要去掉货币中无用的符号从而转化为数字。
folderSort: true,
dir: “asc"
sortType: function(node) {
}
在上面的这个例子中,我们返回了node里自定义的属性,因为这个属性的值
是有效的JS日期,Ext可以对其进行排序。这就是一个关于如何通过sortType选项让
TreeSorter对任何服务器端数据进行排序的演示。
return onDate
编辑:
很多时候,如果能编辑节点的值将是很有用的一个功能。在观察分类产品的层
级结构时,你可能希望对产品的种类或者产品的名字做直接的修改,而不希望再去访
问别的页面。那么你就可以通过itor来实现这个功能。
TreeEditor默认在你双击节点标签的时候会为你的节点提供一个用于编辑的
TextField。但是,和drag-and-drop(拖拽)一样,开启这个功能并不会自动向服务器
端保存改动。你需要在编辑完节点后触发某个事件然后调用事件提供的函数来进行相
应的操作:
('beforecomplete', function(editor, newValue, originalValue)
{
});
beforecomplete事件函数有如下三个参数:
1.
2.
3.
editor:用来编辑这个节点的编辑字段;
newValue:输入的值;
originalValue:改动前的值。
// Possible Ajax call?
然而,你需要注意的是editor这个参数不是一个普通的。它有一
些额外的属性,其中最有用的就是editNode——对编辑节点的引用。你可以通过这个
属性来获得节点的id,这个属性在向服务器发请求来和数据库同步编辑的数据时很重
要。
与TreePanel的beforemovenode事件相比,beforecomplete可以让用户通过在
处理函数的结尾返回false来取消编辑改动。AJAX请求需要提供failure处理函数来手
动地还原先前的数值。
现在我们介绍了如何建立一个简单的节点编辑器,但这还意味着我们还需要完
成一些更复杂的功能。TreeEditor的构造函数里有两个可选的参数(一共三个,后两个
可选)。一个是field的配置对象,一个是TreeEditor的配置对象。field的配置可以是
一下两者之一:
标准TextField编辑器的配置对象;
已经建立的表单字段的实例。
如果是后者,你可以在此采用NumberField,DateField或者其他的
。
第二个可选参数可以让你配置TreeEditor,只要一点小小的改动就能实现令人
激动的功能。例如,我们可以使用cancelOnEsc来允许用户通过按下Esc键取消任何编
辑;或者使用ignoreNoChange来避开编辑完成事件——如果值在编辑后并没有改变。
修剪树枝:
关于TreePanel,还支持一些其它的技巧——改变selection model(选择模
型),过滤节点,以及显示背景菜单等。所以,让我们现在就学习它们。
Selection models(选择模型):
在我们之前的示例代码里,我们可以通过拖拽和编辑TreeNodes来即时改变
tree。TreePanel默认使用single-selection model(单选模型)。我们之前的代码都需要
去选择节点,但是对于tree来讲,简单地选择一个节点并不能满足所有的需求,所以
我们需要知道控制选择方式的更多的方法和特性。
一个很好的例子就是,我们在选择一个节点以后,会自动产生一个信息面板来
展示节点的细节。也许你有一个tree用来展示产品,点击一个节点需要显示该产品的
价格和库存量。我们可以使用selectionchange事件来让这一切得以实现。我们还是使
用先前的代码做开始,我们添加一下的代码:
('selectionchange', function(selModel, node) {
});
var price = ;
selectionchange事件的第二个参数node使得我们很容易获得自定义的节点属性
值。
如果我们允许多节点选择呢?我们怎么去实现,我们怎么去处理
selectionchange事件呢?我们可以使用electionModel来建立我们的
TreePanel:
var tree = new nel({
});
配置就是这么简单。虽然selectionchange的处理方法和默认的selection model
很相似,但是还是有重要的区别。第二个参数是节点的数组,而不是单一的节点。
renderTo:'treeContainer',
loader: treeLoader,
root: rootNode,
selModel: new electionModel()
selection model并不只局限于获得与选择相关的信息。它还允许控制当前的选
择。例如:elections()方法在你处理有关多节点事件之后可以
帮助你清除所有的选中状态。DefaltSelectionModel有方法(selectNext和
selectPrevious)可以让你在tree中定位,在节点的层级中根据需求向上或者向下移
动。
背景菜单(context menu):
我们现在已经介绍了很多TreePanel提供的特性,所以让我们用一些练习来巩
固一下。当你右击节点时弹出一个context menu,这是一种界面上的“捷径”。我们
使用的代码在之前的段落中已经介绍过,首先,让我们建立menu,然后把它加到
TreePanel中:
var contextMenu = new ({
});
items: [
{ text: 'Delete', handler: deleteHandler },
{ text: 'Sort', handler: sortHandler }
]
('contextmenu', treeContextHandler);
TreePanel提供了一个contextmenu事件来监听右击节点。注意,我们的监听器
不像之前的例子中一样采用匿名函数——为了让代码更易读。
首先,treeContextHandler用来处理contextmenu事件:
function treeContextHandler(node) {
}
这个函数在调用时有一个node参数,我们需要在这个函数中先选择这个
node。然后我们用show方法弹出context menu,这个方法有一个参数,用来说明弹出
的位置。在这个例子里,我们的位置为TreeNode的文本处。
();
(hor());
菜单处理:
这个菜单有两个入口——Delete和Sort,让我们看下Delete的处理函数:
function deleteHandler() {
}
利用我们之前的有关selection model的知识,我们可以获得在
treeContextHandler中选择的节点,然后调用它的remove方法。这将从TreePanel中删
ectionModel().getSelectedNode().remove();
除这个节点和它的子节点。注意,我们不把改变传递给服务器,但是如果你需要这么
做,TreePanel有remove事件,你可以用它的处理函数来提供这个功能。
Sort处理函数如下:
function sortHandler() {
ectionModel().getSelectedNode().sort(
function (leftNode, rightNode) {
return (rCase() <
rCase() ? 1 : -1);
}
再一次地,我们使用selection model来获得选中的节点。ExtJS提供了sort方
法,这个方法的第一个参数是一个函数,拥有两个参数:一对节点。在这个例子里,
我们通过节点的text属性来进行降序排序,但是你可以利用别的自定义节点属性。
N:使用这个方法和TreeSorter的排序不冲突,因为TreeSorter的排序只监听
beforechildrendered、append、insert和textchange事件。其他的改动并不受影响。
Delete动作将彻底地删除选择的节点,Sort动作将依照text标签来对子节点进
行排序。
}
);
过滤:
lter类在ExtJS 2.2中被冠以“试验”的标记,所以我只简要介
绍。它用在用户想要根据节点某个特定的属性去检索节点时。这个属性可以是text、id
或者其他在创建节点时自定义的信息。让我们利用之前的context menu来演示过滤功
能,首先,我们需要建立TreeFilter:
var filter = new lter(tree);
你需要回到context menu的配置里,在items里为其添加一个新的入口:
{ text: 'Filter', handler: filterHandler }
我们现在需要建立一个filterHandler函数来实现filter动作:
function filterHandler() {
var node = ectionModel().getSelectedNode();
('Bee', 'text', node);
}
像别的处理函数一样,我们先获得当前选中的节点,然后调用filter函数。这个
函数有三个参数:
1.
2.
3.
被过滤的值
过滤的属性(可选,默认为text)
开始过滤的节点
我们让被选中的节点作为开始过滤的节点,这意味着我们将对右击的产生菜单
的节点的子节点通过特定的值做过滤。
我们的上面的例子(包含aardvark、bee、cockroach这些动物的例子)不需要
做过滤,但是在某些状况中需要。线上的软件文档(多级且详细),采用过滤可以对
标题迅速检索。你可以使用checkbox或者弹出对话框来让用户输入过滤的数据,这样
会带来灵活的用户体验。
根:
虽然我们演示了很多Ext中树的功能,但是tree真正的强大之处在于它的设
置、方法、各种类提供的加载点。我们已经了解了很多配置TreePanel和TreeNode的
方法,让我们得以实现强大的功能。然而,还有很多的配置项可以加强我们的tree,
我们将会对一些有趣的配置进行说明。
调整TreePanel:
默认的,TreePanel有很多图形界面上的加强配置,可以满足一些需求。例如,
把animate设置为false可以阻止节点的展开和收拢的平滑的动画显示效果。这点在用
户频繁展开关闭节点时很有帮助,可以放置动画效果带来的显示不畅。
因为TreePanel是扩展自,所以它支持所有标准的Panel的功能。它可
以支持tbar和bbar(顶部和底部工具栏),header和footer元素,收起/展开的功能。
TreePanel同样可以包含于rt和之中。
装饰:
对于纯粹的装饰属性,TreePanel提供了lines选项,当它被设置为false,将把
TreeNodes之间的层级导航线禁止掉。这点在形成简单的tree时很有用,可以放置界
面的混乱。
hlColor属性适用于drag-drop属性开启的tree。它控制节点的颜色高亮(属性
值为十六位数字串,例如990000),当节点放下时被触发——可以通过设置dlDrop属
性为flase来禁止。设置trackMouseOver属性为false可以禁止悬停在某个节点上时产
生的高亮。
调整TreeNode:
在很多情况下,你不能人工地建立TreeNode(除了root节点),所以你可能
想,那些配置选项对你来说没什么用。其实不是这样的,因为不只是id和text属性可
以拿来创建节点——所有JSON中的TreeNode属性(满足配置属性要求的)都可以被
用来建立节点。如果你有如下样子的JSON:
[
]
你将获得一个开始为disabled的节点,但是一旦它设置为enabled,它将成为到
的链接。
{ text: 'My Node', disabled: true, href: ''}
这个功能在传递应用的特殊信息的时候很有用。例如,你的服务逻辑要求你某
些节点不能拥有子节点。这是你设置allowChildren: false就可以实现这样的功能(该节
点不能作为drop的目标)。你还可以设置draggable: false,这样你就可以组织某些节
点的的拖放。我们可以通过设置checked: true来使得某个节点拥有checkbox(事实
上,checked不管设置为true或者false都起作用)。这些配置选项允许你规定节点的
行为。
还有许多其它的和TreeNode相关的配置。你可以使用icon配置来提供自定义
的图标,或者通过cls属性来提供CSS样式。qtip选项允许你弹出tooltip——可以是对
节点的说明。
控制操作:
当TreePanel被配置后,我们可以操控它的节点。TreePanel允许你在不同的层
级之间“航行”,从选择的节点转移到父节点或者子节点,或者顺着当前的层级向上
或者向下移动。我们也可以根据节点的路径选择或者展开节点,也可以以此找到某个
节点。expandAll和collapseAll方法可以使我们展开合起所有节点,可以被用来还还原
默认的状态。每个方法都有一个布尔值的参数,用来说明改变是否需要animate(有动
画效果)。
expandPath方法的第一个参数是节点的path(路径)。这个path唯一的利用层级
确定了某个节点——例如:/n-15/n-56/n-101。
我们从这个路径可以知道,目标节点的id为n-101,n-15是root节点,root节
点有一个id为n-56的子节点。如果你了解XPath,这个就很好理解。如果你不了解的
话,你可以把她和IP地址做对比——提供了为一的路径引用方式。
通过向expandPath传递这个参数,tree可以定位到指定的节点,并且展开之。
想象一下代码:
('Node', 'Please enter a product name',
function(btn, text){
});
if (btn == 'ok'){
}
var path = GetNodePathFromName(text);
Path(path);
GetNodePathFromName函数可以查询服务器并且返回节点的id,可以通过用户
的输入快速定位节点。eById也可以通过类似的方式使用。不仅是展
开节点,还可以进行进一步的控制。
在某些环境下,你可能需要做一些撤销动作,这是你需要获得节点的路径。
h提供了这样的功能,你可以用这个方法来存储节点的位置。
更多的方法:
TreeNode还有很多其他的方法。我们已经介绍了sort和remove,但是现在我
们可以添加一些基本应用程序的方法,如collapse和expand、enabled和disable,
expandChildNodes和collapseChildNodes(可以用来展开合起所有的子节点)。findChild
和findChildBy方法可以允许简单或者自定义的对节点的搜索,以下这个例子我们用来
查找第一个price属性值为300的节点:
var node = ild('price', 300);
在某些情况下,你可能需要对大量的节点属性进行操控,你可以使用
ild方法:
ild(function(currentNode) {
});
因为第一个参数是一个函数,我们可以展示不同的需求带来的逻辑。
+= 30;
事件捕获:
我们已经演示了很多用户和tree交互的方法,但是还有很多有用的事件。先
前,我们讨论了TreeNode的checked配置项的用法,当checkbox被勾选或者取消,
checkchange事件被激发。以下代码可以使得选中状态高亮显示:
('checkchange', function(node, checked) {
ild(function(currentNode) {
Check();
}
});
我们让选中对TreeNode的子节点都生效,我们可以高亮显示节点来清楚地显
示选中状态,或者实现其他的逻辑,例如在页面的任何位置展示新被选中的节点的信
息。
TreePanel事件的一个更通常的应用就是检查改动和与服务端同步改动。例如,
一棵分类产品的树有着逻辑约束——某些特价商品需要表明最高价格。我们可以使用
beforeappend事件来检测:
('beforeappend', function(tree, parent, node) {
return <
mPrice;
});
这个示例演示了ExtJS提供的一种模式——返回false来取消动作的执行。在这
里,如果价格超过了最高价,就会返回false,节点就不会被加入。
记录状态:
在很多应用中,TreePanel是用来做导航的,展示层级结构,没个节点是一个
HTML的链接。在这种场景里,如果用户希望观看多个页面,一个接着一个,默认的
TreePanel的行为会导致混乱。因为tree在页面刷新时不会保持状态,当用户返回时,
所有的展开的节点将被收起。所以,当用户需要经常定位他们感兴趣的页面时,往往
会因此失去耐性。
StateManager(状态管理器):
现在我们有一个管理TreePanel的好方法,可以方便地存储和还原状态。我们
需要存储每个TreeNode的展开的状态,当页面重新加载的时候,我们可以重现展开的
状态。我们可以使用r和它的CookieProvider来存储展开状态。我们可
以这样初始化:
vider(new Provider());
这是一个标准地设定state provider的方式,我们现在需要建立我们所需要存储
的东西,我们选择存储节点的路径——这可以使得用户方便地访问他/她所感兴趣的最
末端的节点:
('expandnode', function (node){ r.
});
在这段代码里,我们使用expandnode事件来记录路径(使用h
方法)。这样treestate就包含了最后一次展开的节点。我们可以在页面加载的时候检
查这个值:
var treeState = (“treestate");
if (treeState)
Path(treeState);
set(“treestate", h());
如果treestate之前被记录过,我们使用它来展开最后一次展开的节点。
警告:
需要强调的是,这个只是单纯地执行。它不会去管你在展开节点后是否合起
来,因为合起节点的状态不会被保存。所以当你还原状态的时候,合起的节点又将展
开。通过对collapsenode事件进行处理,我们可以解决这个问题。另外,对于展开多
节点也存在着问题。如果很多节点同时展开,只会展开最近展开的一个。存储一个展
开节点的数组是一个好的解决办法。
总结:
用十一行代码展示一个丰富的nel留给了我们很深的印象。本章
还进一步演示了TreePanel的强大功能——它为我们提供了丰富的配置选项。
异步加载是一个很重要的功能,因为它提供了展示大量动态信息的一种方式。
在中这个功能得到了很好的处理,这意味着无论对于开发者还是最终用户都能
得到好处。
尽管很强大,但是类仍然让人感觉是一种很轻量级的应用。使用配置
选项以及各种TreePanel和TreeNode提供的方法、事件可以方便地驾驭这种“强大”
(并不仅仅局限于这些类里)。TreeSorter和TreeNodeUI也是解决问题的关键所在,
提供了自定义显示和用户体验的功能。因为nel拓展自,而
又是BoxComponent的拓展,我们可以获得强大的component(组件)和
layout(布局)的支持,这意味这tree可以被轻松地包含于中,而这是我
们下一章讨论的主题。
版权声明:本文标题:Extjs教程_第八章_Tree(树) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1720649195a835842.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
更多相关文章
xp系统Google Chrome浏览器数据文件地址修改
Google Chrome浏览器在安装和使用的时候,没有设置相应的数据地址,因此都放在了C盘,随着时间推移,浏览器下用户数据越来越大࿰
Chrome浏览器指定用户数据的保存路径
这里将用户数据放到Chrome浏览器的当前目录 我现在的浏览器路径是 D:softChromeApplicationchrome.exe 选中它右键发送桌面快捷方式,将快捷方式剪切到chrome.exe同一
WR703N路由器刷openwrt后续之------打开数据双传。
之前在刷完openwrt之后就试图用手机上的软件来对路由器发送数据进而操控底层节点。但是改了半天之后,还是实现不了这些功能。(比如有的时候只能发送一次数据,或者有的时候只能打
【干货】使用EnCase来分析windows 7文件系统------认识元数据记录$MFT,数据恢复
来源:Unit 6: Windows File Systems and Registry 6.1 Windows File Systems and Registry Windows NTFS File System 现
算法数据结构(三十四)----根据对数器找规律&根据数据量猜解法&分治
对数器找规律 1)某个面试题,输入参数类型简单,并且只有一个实际参数 2)要求的返回值类型也简单,并且只有一个 3
AI、ML 和数据工程 | InfoQ 趋势报告(2021 年)
本文要点 我们看到越来越多的公司正在使用深度学习算法。因此,我们将深度学习从创新者转移到了早期采用者的类别中。与此相关的是,深度学习也面临着新的挑战,比如在边缘设备上部署算
移动硬盘无法读取数据,总是提醒格式化
解决办法:运行cmd,输入chkdsk G:f,回车即可。
群晖第二篇-挂载外接移动硬盘拷贝数据
1.首先将移动硬盘接入前面的usb口中,然后依次点击“控制面板”->“外接设备”,然后查看硬盘是否挂载成功 此时则正常,ps:西数的一块移动硬盘不
移动硬盘修复的有效方法,恢复移动硬盘的数据这么做!
硬盘是计算机中的存储设备,是非常重要的部分。当硬盘发生故障,很可能会导致我们电脑里面的数据丢失。所以移动硬盘发生故障,我们一定要想办法修复它。 有没有什么操作方法&
excel VLOOKUP和MATCH结合使用匹配数据
IFERROR(VLOOKUP($B452,表1-5!$A$1:$N$106,MATCH(C$1,表1-5!$A$1:$N$1,FALSE),FALSE)&"","")
数据科学 IPython 笔记本 四、Keras(下)
四、Keras(下) 原文:keras-tutorials 译者:飞龙 协议:CC BY-NC-SA 4.0 4.7 用于 MNI
ChatGPT 将如何颠覆数据和分析领域(翻译)
ChatGPT 将如何颠覆数据和分析领域 每个人都在谈论 ChatGPT。许多人也在使用它。这个新的人工智能工具由 OpenAI 推出,它在各行各业和各行各业的人们中引起了轰动。该工具可以为查询提供明确的响应、编写代
chatgpt一个新增自定义功能,可以用来进行数据收集,问题答案收集,读书的chatgpt
不需要多次搜索就能找到尽可能多的结果,并自动过滤部分重复内容,更加高效便捷的搜集数据和问题答案。也可以用来总结2021年以前出版的各种有影响力的书籍,在有限时间里了解各种书籍
windows,mysql导入还原数据命令,恢复sql文件数据方法
1、打开CMD命令输入框,输入:mysql -u root -p,然后回车 2、输入数据库密码 3、选择需要操作的数据库:use 数据库 4、然后使用s
【CVutils】计算机视觉:视频图像(清洗、裁剪、人脸区域抓取等)数据预处理&数据集制作 || 代码合集
【start:2023.06.15】 文章目录 1. FFmpeg1.1. 下载1.2. 万能观影1.3. 拷贝视频1.4. 裁剪视频1.5. 横向拼接视频 2. OpenCV2.1. 安装2.1.1. 安装cv2库2
数据中台为什么那么火?
数据中台为什么这么受欢迎? 为什么有这么大的需求? 数据实际上是一个非常传统的行业。 在有软件开始的那一天起,数据这个行业就存在了。比如说原来最早的时候
如何用Python和Pandas分析犯罪记录开放数据?
作者 | 终身学习者,大学教师。阿里云栖社区专家,北得克萨斯大学访问学者。喜爱鼓捣 Python 和数据。 来源 | 玉树芝兰(公众号id:nkwang
Milvus 核心设计(1) ---- 数据一致性的等级及使用场景
目录 背景 Milvus的数据一致性 设置数据一致性等级 等级类型 PACELC定理 level详细解释 Strong Bounded staleness Session Eventually 总结 背景 分布式
360安全浏览器不支持的属性
css的text-align的justify属性;text-decoration的blink属性;好像还不支持pre标签,在w3的css中测试pre元素时࿰
java查询数据导出excel并返回给浏览器下载
效果图: 1.点击导出表按钮 2.接着就会出现下图 3.点击上图中的确定按钮再接着就会出现下图 4.点击上图中的保存按钮接着就会出现下图,浏览器下载完成后的提示 5.打开下载好的文件如下图 好了,废话不多少,上代码 jsp前端代码 &l
发表评论