| 发表于:2007-07-24 09:16:151楼 得分:0 |
mztreeview 1.0 开发文档 文档 开发文档: http://www.meizz.com/web/article.asp?id=436 控件下载: http://www.meizz.com/web/download/mztreeview10.rar 应用示例: http://www.meizz.com/web/demo/mztreeview10.htm 说明 mztreeview 1.0 是数据一次性加载,客户端节点异步展示的web脚本树。mztreeview 1.0 的理论节点数设计上限为十万节点,在节点数三万的情况下页面打开时间小于 3 秒。无限层次无限节点的数的层级组成方式:id parentid。即每个节点除本身的节点id之外还有它的父层节点id,通过这种方式就可以组合成无限层级的树了。 在 mztreeview 里都有一个虚的根节点,其id为0,用户可见的根节点其父节点id皆为0 mztreeview 1.0在数据库库表里的字段名称:字段名 字段的具体说明 id 节点id(不可为0,可以是数字或字符) parentid 本节点的父节点id(若本节点已为根节点,此处填0) text 节点的显示文本(一般不允许为空,不过有一种情况例外,即根节点,若根节点文本为空,这个根节点将不会在页面里显示) hint 节点的说明注解 icon 节点的图标,mztreeview 1.0允许每个节点拥有不同的图标(对应的名字在类里的icons和iconsexpand定义) data 节点挂的数据,格式是 param=value¶m=value&... url里?后的那串字符串格式, url 每个节点允许拥有不同的链接,它为空或者为#时,树里这个节点的链接,点击将无反应 target 每个节点的链接允许在不同的target里打开,为空时取类里的默认值 method 点击该链接时所想触发的脚本语句 特注:每个字段值中不可有冒号: 不可以换行 引号酌情考虑应不与节点字符串的引号相冲突 设计模式 为了达到能够在浏览器中快速打开多节点树的页面,我做了很多的优化与创新,下面我将详细解说几项最重要的部分: 数据一次性加载 首先我要说的就是数据的一次性加载。在目前的 b/s 架构开发中对于多节点多层次的树,特别是树节点量超过两千的情况下,几乎都是采取数据异步加载来达到目的,即用户需要展开某个节点时,再从服务器端加载下级子节点的数据,数据异步加载最为经典的例子就是 msdn 网站左边的目录树了。异步加载的优点在于可以扩充到无限级无限节点树,树的数据来源可以多样化(数据库或xml文件)等,但是它的缺点也是非常多的:设计模式比数据一次性加载要复杂得多,要考虑到 browser/server 之间的应答,要判断子节点是否含有孙节点,后台数据源的层级关系模型等。对网络传输的信赖性太大,每个节点的展开都需要连一次 server,只要在取某节点数据时网络出现问题,就会导致该节点及其以下的子节点加载失败。而采取数据一次加载的模式只要一次加载成功,服务器就可以不用管它了,服务器压力减轻,脚本设计则完全独立,对整棵树节点的检索可以在客户端完成,节点展开响应速度快等等优势,因此在节点数不多的情况下数据一次性加载更有优势,那么这个节点数不多不多到底多少节点量为平衡点呢?就 asp.net 里带的那个 treeview 来说,在一两千节点以下一次性加载比较具有优势,而 mztreeview 1.0 在节点量三万至五万以非常具有优势。 节点信息的压缩传输 在浏览器里显示的树结构其实都是一个个 html 元素组合起来的,在 web 页面里的树都是根据树节点的信息组合成一串的 html 元素列来显示,这一步从节点信息到 html 的转化可以在两个地方生成:一个是在服务器端,一个是在客户端。在服务器端生成的优点在于不须考虑客户端的浏览器的兼容性,节点信息的可控性非常强,但是它的缺点也是非常大的:加重服务器的负担,增加网络传输量。在服务器端直接生成树节点的 html 给服务器带来的压力是显而易见的,也是非常巨大的,估计只要有几十个并发连接就能让服务器暂时停止响应了。这种直接在服务器生成树的做法在实际运用环境中也有人使用,不过本人非常不赞成这种做法。当然也有人直接将树生成为一个静态文件放在服务器端,这种做法对于树节点相对固定不变的情况还是非常有利的,只需要生成一次,以后就不需要再生成了,服务器的压力也非常小,但它的弊病在于可变化性太小,比如说不同的权限能看到的树节点的不同这种情况,用这种生成静态树放在服务器端的做就没有办法解决,且不管是服务器端动态计算还是直接生成静态树文件放在服务器端都有一个避免不了的问题就是网络传输量巨大。可以计算一下,一个树点所需要的html字符量大约300到600字节之间。即含有一千节点的树的网页大小就有300k到600k,给网络造成的压力是非常巨大的,所以mztreeview 1.0采用了节点信息的压缩传输,大至一千节点的总传输量在30k左右,这可以差了一个数量级呀。本树将每个节点所必要的信息组合成一个字符串序列,传递到客户端,然后在客户端再用客户端脚本对这些信息进行分析,再生成一个个的节点html,这也符合了web的分散计算的原理,当然服务器端可以有选择性输出部分节点,这样又做到节点的灵活多变性。 传输的节点信息的可扩展性 服务器端将节点的必要信息组合成一个字符串序列传递到客户端,然后客户端再用脚本对这个字符串序列进行分析,生成树的节点,那么这个字符串序列对整个树的生成的效率就有重要的影响了。我也参照过很多组串传输的例子,在一般的做法当中大多采用函数的参数方式传递。比如说定义一个函数 funname(p1, p2, p3, ...),然后服务器组串的时候就按位置给定数据。这种组串的弊病是非常大的,首先就是位置绝对错不得,只要有一个位置数据出错,这个节点的信息就乱了,对于那些在函数里已经定义的但节点里没有的信息也得用空字符串补上,诸如:(p1, " ", p3, p4, " ", " ", " "),且万一这种组串的对应分析函数发生了变化,那么这种串就算是废了,得重新定义服务器端的字符串位置序列了,可以说这种组串的方式可扩展性极差。 节点信息组串传输的另一种常用模式就是xml。xml以它的无限可扩展性已惭有代替html称霸web的味道了。xml最大的优点就在于它的无限可扩展性,可以用任意的tagname名,可以有任意的attribute名,节点与子节点已经有层级的关系,用xml来做web树的数据源其实是最理想的,msdn的资源目录树就是采用xml作为传递的字符串,它唯一的不足之处就是不是所有浏览器都能很好地支持它,特别是在一些低版本的浏览器中,所以我只好忍痛割爱没有启用xml作为中间的传媒。那么是不是有可能结合xml的扩展性对第一种组串的方式进行改进呢?当我愁眉不展的时候,html里的style样式表写法跳入我眼,样式的写法是 "param1: value1; param2: value3; ... ",哈哈,这不是现成地给我指明了路吗?这种写法拥有xml的可扩展性,位置顺序的随意性,又是传统的长字符串,正合我意也!服务器给定这种数据源字符串,我不光可以在treeview里用它,还可以直接做outlook bar,下拉式层级菜单,右键层级菜单的数据源,豁然开朗也!我写了一个函数专门解析这种文本:getattribute()。 客户端节点数据的存储方式及快速检索 现在数据源准备好了,数据传输也已做到最大优化了,下面就是客户端的脚本解析了,而这一步也正是树生成的效率瓶颈所在。由于我没有采用xml做为数据源,所以我这里就不讨论xml+xsl和xmldom的模式,而只考虑html+dom模式了。在html+dom模式下客户端存储的方式有很多种,我就曾经看到过一种直接将字符串输出在多行文本框 <textarea> 里的,但归究起来最常用的方式就是用一个数组来存放节点信息,不过就算是用数组也是种类多多,比如说数组里套数组,节点通过记录父节点在数组里的索引号表示层级的等等,说到数组存放树节点模式,我推荐阿信写的那棵树。在服务器端组织好脚本及节点字符串,客户端浏览器加载这个页面的时候顺序执行其里面的脚本,将一个个节点做最初步的解析,然后再一个个地add到数组中去。这种流程看起来似乎没有什么问题,在很多的传统c/s结构编程中也就这种模式,但是随着节点数的增多,这种流程在b/s里的缺点就出现了:脚本的执行效率不如强语言高!我做过测试,在5000节点的数据量时这一步操作将耗时1秒钟,也许你认为这1秒钟不算长,哪里有5000这么多节点的树?但对于一个程序员来说,严谨是第一位的,若存在优化的可能性,情况出现的可能性,我们就得将它考虑到。那么有没有可能再进一步优化呢?当然有,否则我就用不着这么大费口舌在这里讲了。既然在脚本里执行 for 循环插入数组效率不高那我不用循环,且考虑到在数组里这么多节点中搜索我想要的某几个节点,还得用循环,所以我干脆就不再用数组来存放树节点了,那用什么呢?说到这里我得插几句题外话,客户端脚本也可以写一些类,虽说写出来的类没有强语言那么好,继承性不好等,但脚本终究还是可以写出一些简单的类的。类可以定义属性,也可以定义方法,并且访问属性的时候可以通过属性名下标直接访问到属性值,关于脚本里如何写类,大家可以参考我在javascript和vbscript里对这方面的详细说明。呵呵,说了这么多的题外话,不过相信大家也猜到了,新的节点存储方式就是类的属性自定义扩展方式。这种存储方式随着页面的打开,页面里的脚本被执行,类的属性值不需要做任何添加的动作就直接写到内存当中,比数组模式少去了add操作,这一步从字符串到内存的时间就是页面打开的时间,我测试了一下,5000节点的树用这种方式打开,只需0.1秒呀,与数组模式速度整整差了一个数量级呀!且这种模式还有一种好处,在几千个节点里要找到目标节点,只需要知道节点对应的属性名,一步就可以直接找到。 | | |
|