当前位置: 代码迷 >> JavaScript >> Extjs TreePanel示范
  详细解决方案

Extjs TreePanel示范

热度:371   发布时间:2013-08-01 15:23:18.0
Extjs TreePanel示例

转自:http://legend2011.blog.51cto.com/3018495/1171733

?这几天用到了Extjs的TreePanel来创建树形菜单,在网上没瞧见一个好的示例,遂决定写一个,供后来者参考(本文下方的“附件下载”可下载本示例的完整源代码)。

????? 先创建一个雏形,代码如下:

  1. var?tree?=?new?Ext.tree.TreePanel({ ?
  2. ???????title?:?'主菜单', ?
  3. ???????width?:?200, ?
  4. ???????autoScroll?:?true, ?
  5. ???????singleExpand?:?true, ?
  6. ???????rootVisible?:?true, ?
  7. ???????animate?:?true, ?
  8. ???????//树加载器 ?
  9. ???????loader?:?new?Ext.tree.TreeLoader({ ?
  10. ??????????dataUrl?:?'tree/treeNodeAction_listTree.action'?
  11. ??????????????}) ?
  12. ????}); ?
(代码1)
????? 注意这里使用了一个loader属性,其值为一个Ext.tree.TreeLoader对象。根据它的名字,我们就能推测出这个对象是用来加载树的,而其dataUrl属性则指定应从何处加载树的结点信息。

????? 紧接着创建根节点,并将此根结点设置为树的根:

  1. var?root?=?new?Ext.tree.AsyncTreeNode({ ?
  2. ??????????????id?:?'root', ?
  3. ??????????????text?:?'根', ?
  4. ??????????????expanded?:?true?
  5. ???????????}); ?
  6. //将此根结点设置为树的根 ?
  7. tree.setRootNode(root);?

(代码2)

????? 这里注意以下几点:

????? 1、AsyncTreeNode是一种异步加载的结点,即每次只加载本结点的直接子结点,而子结点的子结点(即当前结点的孙子结点)则在需要的时候再加载,这就提高了响应速度;

????? 2、AsyncTreeNode也有loader属性,它的值继承自TreePanel中的loader属性(见代码1)。根结点使用此loader来加载它的子结点信息并创建子结点,而子节点也是AsyncTreeNode对象,它们的loader属性值也来自TreePanel的loader属性,它们也将使用此loader来加载自己的子结点信息,以此类推;

????? 3、后台发送来的代表子结点信息的JSON字符串必须以方括号“[]”包含,如本例加载根节点的子结点信息的JSON字符串如下:

[{id:'module1',text:'模块1',leaf:false},{id:'module2',text:'模块2',leaf:true,url:'demo/module2.jsp'}]

(代码3)

????? 加载效果如下图所示:

(图1:主菜单截图)

????? 4、当加载结点的子结点时,会向后台传送一个node参数,值为当前结点的id。如加载根节点的子节点时,会把根节点的id值“root”(见代码2的根节点的id属性)传到后台,FireBug的截图如下:

(图2:node参数截图)

????? 这样,后台就会从数据库中读取那些父结点的id为node值的结点信息,即当前结点的子结点信息。这样,本示例的结点信息在数据库表中的形式就如下图所示:

(图3:表中的结点信息)

????? 注意观察parent_id值为root的两个结点,即为图1主菜单截图中的根结点的两个子结点。

????? 同理,后台向前台发送结点信息时,也应该提供该结点的id值(参见代码3的JSON字符串),供将来加载此结点的子结点时使用。

????? 到目前为止,我们已经成功生成了树,并可以动态加载其结点信息。但我们最终的目标应该是点击TreePanel(一般放置于页面的左边)的某个叶子结点时,能在页面右部显示相关的功能页面。为了实现这个功能,应该使用Viewport,其布局为border。然后将TreePanel放置于Viewport的西区,再新建一个TabPanel,放置于Viewport的中央区。为TreePanel添加click事件处理函数,在这个函数中,若相关的页面没有被加载,则新建一个Panel加载此页面,并添加到TabPanel中,然后设置此Panel为活动的,显示给用户;若相关页面已被加载,则直接设置其为活动的即可。具体代码如下所示(注意:其中的center即为位于中央区的TabPanel):

  1. listeners?:?{ ?
  2. ??????????click?:?function(node)?{ ?
  3. ?????????????//?node代表被点击的结点,通过其attributes属性读取 ?
  4. ?????????????//?后台传来的url等属性,url指该结点指向的页面 ?
  5. ?????????????var?url?=?node.attributes.url; ?
  6. ?????????????var?id?=?node.attributes.id; ?
  7. ?????????????//?从center中获取相关的Panel ?
  8. ?????????????var?tab?=?center.getItem('tab_'?+?id); ?
  9. ?????????????//?只有当url存在,才进行后续处理 ?
  10. ?????????????if?(url)?{ ?
  11. ?????????????????//?如果相关的Panel已存在,直接将其设置为活动的即可 ?
  12. ?????????????????if?(tab)?{ ?
  13. ????????????????????center.setActiveTab(tab); ?
  14. ?????????????????}?else?{ ?
  15. ????????????????????//?否则创建一个Panel,用于加载url指向的页面,然后 ?
  16. ????????????????????//?将此Panel添加到center中,并设置其为活动的 ?
  17. ????????????????????tab?=?new?Ext.Panel({ ?
  18. ????????????????????????title?:?node.attributes.text, ?
  19. ????????????????????????html?:?"<iframe?src=\'#\'" /span>?
  20. ???????????????????????????????+?url ?
  21. ???????????????????????????????+?"'"?
  22. ???????????????????????????????+?"?width='100%'?height='100%'?frameborder='0'?scrolling='auto'>"?
  23. ???????????????????????????????+?"</ifame>", ?
  24. ????????????????????????closable?:?true, ?
  25. ????????????????????????layout?:?'fit', ?
  26. ????????????????????????frame?:?false, ?
  27. ????????????????????????id?:?'tab_'?+?id ?
  28. ????????????????????}); ?
  29. ????????????????????center.add(tab); ?
  30. ????????????????????center.setActiveTab(tab); ?
  31. ?????????????????} ?
  32. ?????????????} ?
  33. ??????????} ?
  34. ??????}?

(代码4)

????? 需要注意的是,只有叶子结点才有url属性,这一点从代码3的JSON字符串即可看出:id为module1的结点为非叶子结点,因而后台并没有给它传递url信息;而id为module2的结点为叶子结点,就有url属性。

????? 效果如图所示(本示例的完整源代码请于本文下方的“附件下载”处下载):

?

本文出自 “肖凡的专栏” 博客,请务必保留此出处http://legend2011.blog.51cto.com/3018495/1171733

  相关解决方案