`
Relucent
  • 浏览: 211126 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

带选择框的JS树控件2 (为JSTree再次提速)

    博客分类:
  • JS
阅读更多

以前写过一个带选择框的JS树控件
但是当时发现一个问题,第一次选中根节点会明显感觉卡一下。
那是因为子节点的数据还没有生成,选中根节点的话需要初始化全部数据。(那个tree有5000个节点)


于是我思考一个问题,如何让多节点树的页面达到更快的效率

经过测试发现,JSTree的主要效率瓶颈在两个地方。
1.页面HTMLElement的创建
2.树子节点的检索


页面创建一个HTMLElement是很耗时的,无论使用createElement或者是是innerHTML都一样。
而且这一步只能一个节点一个节点慢慢地生成,虽然可以通过减小单个节点的HTML元素量的方法提高一些速度,但是对于对于上千个节点来说仍然需要等上几十秒。
(1个节点如果有5个HTMLElement,生成1000个节点大概3秒左右)

所以只有通过异步展示的方法来进一步减少一次生成的节点数。
页面加载时并不立即生成所有节点的HTML元素,而是用户展开多少节点就生成多少节点,节点的生成发生在用户展开这个节点的时候。 这样减少了每次生成的节点数,消除了使用者的等待时间。

而对于节点的检索,这和数据的组织方式有关。
一般的组织方式是使用数组。(解析XML的话太慢,不考虑。只考虑使用json的情况)
但是在数组中检索一个节点的效率实在不敢恭维,如果节点是N个,那么全部节点数据组装起来的效率就是N*N
在节点少的时候不明显,但是如果有1000个节点,那么明显会发觉延迟了10多秒。延迟速度按指数增加。

MzTree(梅花雪)使用了另外一种方式,他没有使用数组而是使用一个简单对象来存放数组。
并且用一个字符串存放节点的索引关系(将所有的节点名(即类的属性名)join()成一个大字符串)
当需要获得子节点的时候使用正则匹配一步获得子节点ID,从而获得子节点。
经过测试发现,使用正则匹配的算法检索节点效率比使用for循环要高出很多。

这个效率已经满足一般大数据jstree的需要。
(具体算法,去参考MzTree梅花雪)



对于一般的Tree可以通过异步初始化节点数据(不是初始化节点HTML)的方法来解决延迟。
但是如果是checkbox-tree(带选择框的树),却不能使用这个方法。因为对于带选择框的JS树,选中根节点的话,子节点应给也被选中。所以选中根节点,子节点必须存在。 所以节点数据需要一次生成。

但问题是即使使用正则匹配的算法提高了效率,仍然会需要一段初始化的时间。
5000个节点数据全部初始化 使用for需要20-30秒,使用正则匹配算法需要6秒

那么有没有办法进一步提高效率呢?
按照一般Tree的做法初始化一个节点数据需要初始化这个节点的子节点数据,那么也就需要检索节点的子节点数据。(有点绕口)
这个检索子节点数据看来是比较耗费时间的,而且没有更好的提高检索效率的方法。
既然检索没有办法提速,那么有没有不使用检索获得子节点的方法呢?

答案当然是有的,只要我们更改传递过去的数据结构问题迎刃而解。

于是我们直接传递一个拼装好的树结构JSON(节点包含了子节点的数据,子节点的数据中又包含了子子节点的数据....)

数据结构如下:
{
id : 0
childrean : [
  {
   id : 01
   childrean : [
    {
     id : 011
     childrean : [...]
    },
    {
     id : 012
     childrean : [...]
    }
   ]
  }
  ,
  {
   id : 02
   childrean : []
  }
]
}

对于这种结构,页面的Tree可以直接使用而无需解析,免去了子节点的检索所耗费的时间,JsTree展示速度大大提高。
一个5000节点的树,节点数据全部初始化只需要500毫秒。


(其实还有一个优点,使用这种结构的数据JSTree容易扩充,稍作修改就可以改成支持数据异步加载的Ajax-Tree) 


 
 
PS:附件中是一个演示例子,虽然不是最终版本但是可以说明问题。

 

china_2.js 和 china_2_code.js 是节点数据(UTF-8编码)

 

 

参数说明

text        显示节点内容(必须)
id           节点id
checked 选择框选中状态 0 1 2

children 子节点数据

 

创建一个新节点的方法 new TreeNode( {} );

 

 

新建节点可能存在一些问题(单选框选中等问题),节点有checked属性的情况才会出现选择框。

 

 

 

 

 

 

感谢winner720发现的一个BUG

这部分代码要改一下(粗体部分)  TreePanel_0.5.rar

//瀑布(遍历所有子节点)
cascade : function(fn, scope, args){
  if(fn.call(scope || this, (args==null?this:args)) !== false){
    var cs = this.childNodes;
    for(var i = 0, len = cs.length; i < len; i++) {
      cs[i].cascade(fn, scope, args);
    }
  }
},

(以前是 args||this,当节点checked是0的时候可能出现返回this,虽然不影响展示结果,但是会造成一定泄露。改成(args==null?this:args)就不会出现问题了)

 

 

modify:
TreePanel_test_0.x  测试演示版本
TreePanel_all.rar      完整演示版本
TreePanel_0.5.rar    修正了一个内存泄露BUG
TreePanel_2.2.zip    增加了节点全部展开和全部折叠的方法,修正了节点显示时多余的竖线

TreePanel_2.3.zip    修复节点删除时多余的竖线

 

备注:附件请下载最新的版本。 (旧的的版本可能存在未修改BUG,没删除只是为了留作做为备份)

 

这个树最初设计目的快速展示一颗带选择框静态树,虽然也提供了节点增加以及删除等功能,但这些没有经过仔细测试,且不是它的长项。

  • 大小: 28.7 KB
分享到:
评论
31 楼 langshao 2010-05-20  
很好的控件,正是我要找的——关键是出来以及选中的速度.

有一点不明白:china_2.js中的pid,是不是多余的?
30 楼 kolenxiao 2010-04-29  
为什么我下载的版本中var node = tree.focusNode;得到的node都是null?
明白原因了,你的勾选根本没用,只有选中文本才生效
29 楼 kolenxiao 2010-04-29  
到底哪个才是最新版?越看越糊涂
28 楼 gecbzsyj 2010-04-15  
1、最上级:中国,没办法收缩,
2、htm中只能引用china_2_code.js,引用china_2.js会提示JS错误(IE6)
3、建议可以设置参数,比如:自动选择子节点(只选中国,不跟选子节点),自动选择父节点(同个父节点下的子节点全选时,不自动选择父节点)。

以上希望楼主可以完善




27 楼 sd5816690 2010-02-08  
非常好用!!

现在需要打开页面时,展开所有结点
貌似可以在页面加载完成后,调用 expandAll()
但速度太慢了,例子中,4核CPU都需要10秒左右

能不能进入页面时,就把HTML代码写好
调用一个初始化方法,让 HTML 代码和 root 里的数据对应
(HTML代码和 root 都是写好的,只需要初始化就行了)
26 楼 kenee1314 2010-02-04  
如果大数据量,活着级数比较多,能否支持??
25 楼 kenee1314 2010-02-04  
支持分级查找么
24 楼 yemen007 2010-02-04  
这个真的很好用  ,但如果我只想选中“中国”并保持所有其子结点为空应该怎么做?
23 楼 Relucent 2010-01-29  
cuixiping 写道
1、这棵树,如果能够不用jquery更好,为了棵树多用上个jquery似乎不太喜欢。
2、
引用
但是如果是checkbox-tree(带选择框的树),却不能使用这个方法。因为对于带选择框的JS树,选中根节点的话,子节点应给也被选中。所以选中根节点,子节点必须存在。 所以节点数据需要一次生成。
非也。为什么子节点必须存在呢?完全可以不存在!只有用户展开了这个节点的时候,才必须让子节点存在。也就是目前不用看到的,都可以不画,等需要时再绘制。




第一个问题:
好吧,我承认。那个jquery.js是多余的,因为我压根没用到。你可以放心删掉。
otree_old.htm otree_old.js 是以前写的例子,可以一并删掉。



第二个问题:
我说的是数据一次生成,一次加载。

我的节点其实分成两部分,数据模型和 界面UI。这地方我是分开处理的(虽然看起来写到了一起)。
我的节点加载时一定存在的。因为存在的节点方便我注册以及处理。
但是界面上的element并不一定存在。因为浏览器生成一个页面元素是很耗时的。所以只有再需要展示(展开显示)的时候我才会去new一个页面元素。

如上,节点(指页面Element元素)可以在展开时才绘制的,而我也是这样做的
22 楼 cuixiping 2010-01-21  
1、这棵树,如果能够不用jquery更好,为了棵树多用上个jquery似乎不太喜欢。
2、
引用
但是如果是checkbox-tree(带选择框的树),却不能使用这个方法。因为对于带选择框的JS树,选中根节点的话,子节点应给也被选中。所以选中根节点,子节点必须存在。 所以节点数据需要一次生成。
非也。为什么子节点必须存在呢?完全可以不存在!只有用户展开了这个节点的时候,才必须让子节点存在。也就是目前不用看到的,都可以不画,等需要时再绘制。
21 楼 Relucent 2009-12-17  
没有考虑过search,因为我开始考虑的只是如何快速展现一棵树。

但是TreePanel里面有个this.nodeHash变量,记录了节点ID和节点的映射
(一个hash)。
如果是简单的搜索可以用this.nodeHash遍历所有节点。







感谢winner720发现的一个BUG

这部分代码要改一下(粗体部分)

//瀑布(遍历所有子节点)
cascade : function(fn, scope, args){
  if(fn.call(scope || this, (args==null?this:args)) !== false){
    var cs = this.childNodes;
    for(var i = 0, len = cs.length; i < len; i++) {
      cs[i].cascade(fn, scope, args);
    }
  }
},




以前是 args||this,当节点checked是0的时候可能出现返回this的BUG,改成(args==null?this:args)就不会出现问题了。
20 楼 popsoft75 2009-12-16  
楼主的tree控件很不错,但是缺了search功能。在这方面是如何考虑的?
19 楼 Relucent 2009-11-17  
liuweifeng 写道
兄弟,最后一个附件,TreePanel_all,我解压出来运行TreePanel.html,在Chrome里探出alert是108,在FireFox里弹出提示是107,好像有点问题。


= =!

你在提出问题之前难道从不自己看代码吗?

TreePanel.html 31行 alert( (new Date().getTime()-l0));

var L = new Date().getTime();
tree = new TreePanel({
 'root' : root
});
tree.render();
alert( (new Date().getTime()-L));



那个 alert 打印的是初始化Tree花费的时间。

这只能说明不同浏览器初始化Tree的速度不一样。

说Chrome刷出这个树花了108毫秒,FireFox用了107毫秒,IE6用了815毫秒。


(PS:顺便说一下这个树大约有3525个节点。)
18 楼 liuweifeng 2009-11-14  
兄弟,最后一个附件,TreePanel_all,我解压出来运行TreePanel.html,在Chrome里探出alert是108,在FireFox里弹出提示是107,好像有点问题。
17 楼 ryanwangprc 2009-11-13  
楼主能不能提供一个终极版的 谢啦
16 楼 ycmag 2009-10-29  
兄弟,附件的链接失效了,点击编程无法访问的网页了
15 楼 萧十一狼 2009-10-25  
在后台构造那个JSON结构字符串很慢啊, 我用的是穷举遍历,每个节点一层一层遍历构造的。 你们怎么做的,怎么做才能快。  这个树确实很快,  但是后台构造那个符合条件的结构字符串很慢, 新手求解。
14 楼 cn-done 2009-10-24  
新添加的节点貌似前面没的checkbox 不支持选择哦 
13 楼 lqixv 2009-10-20  
希望能完善一下
12 楼 zhongxuchen 2009-10-16  
能不能再强化一下,提供动态树正在加载效果?(即像extjs中的树一样,从后台获取时提供一个正在loading的效果),完善一下,打算用你的树在项目中使用

相关推荐

    jstree目录树控件

    3. **初始化jsTree**:使用`$(selector).jstree(options)`方法初始化树控件,`selector`是树容器的选择器,`options`是一个包含配置项的对象,用于设置初始状态、加载数据的方式、使用的插件等。 4. **处理事件**:...

    使用jsTree实现js树形结构

    jsTree 提供了一套完整的 API,允许你在运行时动态改变树的结构、操作节点、获取用户选择等。例如,打开一个节点: ```javascript $('#jstree').jstree('open_node', '#node_id'); ``` **三、总结** jsTree 是...

    jstree,javascript树形控件

    总之,`jstree` 是一个强大且灵活的 JavaScript 树形控件,能够满足各种树状结构的展示需求。通过深入了解其核心特性和用法,开发者可以轻松地将其集成到项目中,提升用户体验。同时,遵循最佳实践,可以确保项目的...

    js树控件,大家分享

    JavaScript(简称JS)是一种广泛用于网页...总的来说,jsTree是一个强大且灵活的JavaScript树形控件,能够帮助开发者快速构建具有交互性的树状结构。通过深入理解和熟练运用,可以提升Web应用的用户体验和功能完整性。

    手机端js tree

    2. JavaScript:js Tree的核心是JavaScript代码,它负责处理用户交互、数据加载和动态更新。使用事件监听器来捕捉用户的触摸或点击事件,然后执行相应的动作,如展开节点或切换选中状态。 3. 数据源:树的数据通常...

    jstree树形控件

    jsTree是一款功能丰富的JavaScript库,专为在Web应用中实现交互式的树形结构而设计。它基于流行的jQuery框架,允许开发者轻松地在网页上创建和管理树形结构。jsTree不仅提供了基本的树节点操作,如创建、重命名、...

    jstree控件树(可扩展)

    总结来说,`jstree`作为一个强大的JavaScript树形控件,以其丰富的功能、灵活的配置和良好的可扩展性,成为构建交互式树结构的理想选择。无论是简单的展示还是复杂的业务逻辑,它都能够胜任并提供优秀的用户体验。

    带复选框JS树 Javascript树 JS树 树形菜单

    "带复选框"的JS树形菜单则更进一步,允许用户通过勾选复选框来选择或操作树节点,为用户提供了一种直观且高效的多选操作方式。 在构建带复选框的JS树时,主要涉及以下几个关键知识点: 1. **HTML结构**:首先,...

    JSTree(js写的树形菜单,支持加载10000节点以上)

    JSTree是一款基于JavaScript的开源库,专为构建功能丰富的交互式树形菜单而设计。它支持动态加载大量节点,即使面对超过10000个节点的情况,也能保持良好的性能,解决了传统方法在处理大数据量时可能导致的页面卡顿...

    jsTree 左侧导航树大集合

    jsTree是一款基于JavaScript的开源库,专用于创建交互式的树形数据结构,通常被用作网页中的导航菜单或数据组织工具。它支持多种数据源,如JSON、HTML、XML等,并提供了丰富的API和事件系统,使开发者能够自定义行为...

    带复选框JS树,JS带复选框的列表,很好用

    总的来说,"带复选框JS树"是前端开发中一种重要的交互元素,结合了数据结构、用户界面设计和JavaScript编程技术,为用户提供了一种直观的方式来操作和管理层次化数据。通过学习和掌握这种技术,开发者可以提升用户...

    angularjs下拉树控件

    在本文中,我们将深入探讨如何在AngularJS框架中实现下拉树控件,这是一种结合了树形结构和下拉选择功能的用户界面组件。AngularJS是Google开发的一个强大的前端JavaScript框架,它允许开发者构建可维护、可扩展的...

    带复选框的多选树控件(支持XML加载)

    文件名为“TestTree”的示例可能包含了一个演示如何使用这个带复选框的多选树控件的实例。通过运行这个测试程序,开发者可以直观地看到如何加载XML数据、如何处理复选框状态的变化,以及如何响应用户的交互操作。 ...

    jquery超漂亮树形控件

    4. `widgetTreeList.js`:这是树形控件的主要JavaScript实现,包含了所有必要的逻辑和功能,如展开/折叠节点、添加/删除节点、选择节点等。 5. `jQuery Treelist widget_files`:这个文件夹很可能包含了其他支持...

    MFC 树形控件 复选框

    本篇文章将详细探讨如何在MFC中实现树形控件与复选框功能,使得父节点的选择能够影响其所有子节点的选中状态。 首先,我们需要了解MFC的树形控件(CTreeCtrl)基本用法。CTreeCtrl是MFC封装的Windows控件,用于显示...

    js树形控件js树形控件

    JavaScript(简称JS)树形控件是一种在网页中展示层级数据结构的交互式元素,它通常用于展现目录结构、组织架构、文件系统等。在网页设计中,这种控件能够帮助用户以图形化的方式理解复杂的数据关系,通过展开、折叠...

    jsTree.v.1.0中文文档

    - **API方法**:如`jstree('select_node')`选择节点,`jstree('rename_node')`重命名节点,`jstree('get_json')`获取当前树的JSON表示。 - **事件**:jsTree提供了丰富的事件,如`select_node.jstree`在节点被选中...

    PB带复选框的树形控件

    在PowerBuilder(简称PB)这个老牌的可视化编程环境中,开发者经常需要为用户提供交互式的界面,例如带有复选框的树形控件,以便用户可以进行多选操作。这个控件在数据管理、配置选择等场景下特别有用。 "PB带复选...

    wpf_combobox_tree下拉树形控件

    在本文中,我们将深入探讨如何将Silverlight的树形下拉控件转化为WPF(Windows Presentation Foundation)环境下的使用,并以此创建一个名为“wpf_combobox_tree”的自定义控件。这种控件通常用于增强传统的ComboBox...

    jsTree asp.net c# jason demo 控件 案例

    jsTree是一款基于JavaScript的开源库,用于创建可交互的树形结构,广泛应用于网页中的数据展示和管理。它支持多种数据源,包括JSON格式,非常适合与后端编程语言如ASP.NET和C#配合使用。jsTree不仅提供了丰富的API和...

Global site tag (gtag.js) - Google Analytics