Flex中Tree组件实现导航树搜索定位功能及Tree组件的的使用要点

来源:互联网 发布:打车软件市场分析报告 编辑:程序博客网 时间:2024/06/08 08:13

这几天项目中要做一个导航树的搜索定位功能,前端是用Flex做的,以前没接触过Flex。

我的导航树(也是树形菜单)是用Tree组件,ArrayCollection作为数据源实现的。先给大家看看我的效果图:


先说说我实现这个导航树搜索定位功能的思路:

1.在系统启动时,会默认加载若干个树节点数据(因为我的树的数据量比较大,所以不是一次性把数据全部加载完,而是用户点击展开某个节点时,再去数据库加载相应节点的数据,如果是数据量比较小的话,可以将所有节点一次性加载完成,在这个的基础上做搜索定位会简单很多,这个稍后再说)。

2.当用户输入某个要定位节点的名称之后,我会去数据库中进行模糊匹配,找出该名称的节点可能为哪些个。如果只匹配到一个则直接定位,如果匹配了多个,则将这些节点的详细信息展示出来,让用户自己选择去定位具体的哪一个节点。

3.当用户选择定位某个节点后,再去数据库中查找相关的节点信息。我实现搜索定位构造的数据信息主要分为三部分:

1).要展示的所有的节点数据(记做数据data):例如上面图中所示,定位节点为KK羽绒,这份数据就包括KK羽绒节点数据和其同级节点的数据,以及它所有父节点数据和与其父节点同级的节点数据,当然其父节点的同级节点的子节点数据可以不用获取出来,例如上面的新昌县的子节点的数据就可以不用查询出来,只需要新昌县这个节点的数据就行。

2).要定位的节点的数据和其所欲父节点的数据(记做数据parents):这里不包括要定位节点的同级节点数据和其父节点的同级节点数据。例如上面的例子的话,该数据包括:绍兴市->行政区域->越城区->地名->KK羽绒这些节点的数据

3).要定位的节点的数据(记做数据selectedNode):体现在上面的例子中就是KK羽绒这个节点的数据。

4.在查询出这些数据之后,我会将树的原来的数据源给替换成要定位的数据也是数据data

5.在对树的数据源进行更新处理之后,只需要将指定的节点展开,然后将定位设置为选中状态并让其处于当前窗口的视野范围内就达到了搜索定位的效果。而所有要展开的节点数据我都存储在了parents数据中,因为我构造的数据data和parents具有相同的层级关系,所以只需要在data数据的每一级中找到与parents同一级相同的那个数据展开,一直循环下去直到找到与selectedNode数据相同的那个节点时展开节点操作可以结束,然后将与selectedNode数据想同的那个节点设置为选中,并让其处于当前窗口中,这样定位功能就算完成了。


这里我说一下让节点处于选中状态的方法下面两种都行:

tree.selectedItem = nextNode;//节点数据
tree.selectedIndex = idx;//节点在树中的索引


以下是我展开节点的代码:

opendNode(0,parentNodes,searchNode);//从根节点开始展开
/** * 定位到指定节点 * @paramselectedIndex 树当前要展开节点的索引 * @paramparentNodes  要定位节点的父节点数据 * @paramsearchNode要定位的节点的所有数据 *  * */private function opendNode(selectedIndex:int,parentNodes:Object,searchNode:Object):void {tree.selectedIndex = selectedIndex;//当前要展开节点的索引var selNode:Object = tree.selectedItem;//当前要展开的节点if(selNode.id == parentNodes.id){var nextNodes:Array = tree.selectedItem.children;//得到树上当前展开节点的子节点var nextNode:Object = parentNodes.children;//得到下一个要展开的节点的数据(要定位的节点的其中的一个父节点)if(tree.dataDescriptor.isBranch(tree.selectedItem)){tree.expandItem(tree.selectedItem,true,true);//展开当前节点}for(var i:int = 0; i < nextNodes.length; i++)//遍历当前展开节点的所有子节点{if(nextNodes[i].id == searchNode.id) //如果当前已展开节点的子节点中存在要定位的节点,则定位结束{tree.selectedItem = nextNodes[i];//选中树中定位节点var idx:int = tree.getItemIndex(nextNodes[i]);//得到定位节点在树中的索引tree.selectedIndex = idx;tree.scrollToIndex(idx);//将定位节点展示在窗口内return;}if(nextNodes[i].children.length == 0 || nextNodes[i].close)//如果不是定位节点的父节点{continue;}var index:int = tree.getItemIndex(nextNodes[i]);//是定位节点的父节点,得到其在树中的索引值opendNode(index,nextNode,searchNode);//继续定位下一个节点}}}

另外在上面的实现过程中,我遇到了几个问题:

1.在更新数据源的时候,我最开始是直接用tree.dataProvider = arraycollection,但是这样直接更改树的数据源会引起一个很奇怪的问题,就是第一次定位正确,但后面的定位就会出现问题,所有的数据正确,但就是一直报tree为空的异常错误,后来网上查询资料后,有人说直接通过该方式更改数据源是不被推荐的。后来我就将树的数据源改为绑定的方式,然后通过修改ArrayCollection的数据源来更新树的数据源,然后就成功了!

_treedatas.removeAll();//将树的数据源清空_treedatas.refresh();_treedatas.source = [data];//给树重新赋值,data为Array类型_treedatas.refresh();


2.我在更新数据源之前,也就是上面4行代码执行之前,我做了一个操作如下:

tree.selectedIndex = 0;tree.expandChildrenOf(tree.selectedItem,false);//将跟节点收起
就是先将根节点收起,然后再去更新树的数据源,然后就出现了一个问题:tree.selectedIndex = selectedIndex;

在定位过几次之后,后面再进行定位时展开节点的就会出现上面这行代码不起作用,赋值不成功,然后节点展不开无法实现定位效果,这个问题当时纠结了我3天都没解决,后来一老同事看了我代码后让我将上面的两行收起跟节点的代码放到更新数据源之后,结果,奇迹般的解决了,不管定位多少次都不会出现问题。将代码调换顺序之后,逻辑是这样,我跟心数据源数据,然后先将根节点收起,然后再去按照相应顺序展开相应节点,而没换顺序之前,逻辑是这样的:先将树数据源没更新之前的根节点给收起,然后更新数据源,然后按顺序展开节点,我觉得这个逻辑也没什么错误,但就是会出现那个赋值不成功的问题,虽然现在功能实现了,但为什么expandChildrenOf这句代码会引起那个错误,我到现在还没弄明白,如果哪位仁兄知道的话,告知一声,感激不尽!

还有,在没改顺序之前,expandChildrenOf这行代码会去重新发送服务请求,我也不知道是为什么,很是怪异啊这些问题!





原创粉丝点击