`
meladet
  • 浏览: 26771 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

YUI Tree入门(二)各类Node详细分析

阅读更多
   之前简单介绍过TreeView的使用,现在来仔细分析一下YUI TreeView的结构,Tree相关的类如下:

    我们分成3部分看,第一部分是前面几个以Node结尾的类,这些类代表是树上的节点,其中最顶层的是Node,这个类是其他几种Node的父类。Node中有节点所具有的所有属性和方法,比如children,parent,depth,expand(),collapse()等等。
    第二部分是TreeView这个类,这个类就像是一棵树的骨架,他有根有树干有树枝,可以把上面介绍的Node节点挂在Treeview上,Treeview会统一管理记录这些节点。通过TreeView你可以很方便的定位到一个或一些节点,比如 getNodeByElement(),getNodeByIndex,
getNodeByProperty(),getNodesByProperty()。通过TreeView可以控制一棵树是展开还是合拢,可以移除一些节点等等。TreeView就是在全局上控制树上的Nodes。
    第三部分是最后三个类,这三个类主要是个树增加一些动画的效果。

    既然TreeView是整棵树的总枢纽,我们就先从TreeView入手(由于TreeView的 源码太长,我就不直接贴出来,大家可以对照着源码看,碰到比较重要的代码我会把它们贴出来)。   
    首先是TreeView的构造函数:YAHOO.widget.TreeView ( id ),构造方法只有一个参数,就是HTML中的Div元素的ID,这就像是给树挖个坑中下去,以后树在页面上显示就有地方了。构造方法里面调用了TreeView的Init方法,这个方法我们稍后再说。
    TreeView里面有不少属性,不过大多都不用太深究,无非是用来与HTML元素做绑定,记录TreeView的状态等等,这些属性我们只要构建好了树,就由树内部做管理,一般情况下我们都不会使用到。下面挑几个重要的属性做说明:
    YAHOO.widget.TreeView.nodeCount,这是一个静态属性,这个属性记录TreeView上面Node的个数,也就是每次生成一个Node到TreeView上,这个属性值就增加1,这个属性有一个作用就是给Node分配一个唯一的标识,每个Node都有一个属性叫做index,这个index就是由这个属性来分配的。由于这个属性值只增不减,所以永远不会出现重复的。
    YAHOO.widget.TreeView.trees,这是一个私有属性,它是一个关联数组,用来缓存所有的TreeView实例,每次生成一个TreeView的实例就会往trees里面设置一个key(TreeView的Id)和value(TreeView的实例)。这样方便以后通过Id可以直接取到TreeView的实例。TreeView有一个方法:YAHOO.widget.TreeView.getTree(treeId),看看它的实现:
YAHOO.widget.TreeView.getTree = function(treeId) {
    var t = YAHOO.widget.TreeView.trees[treeId];//通过trees属性取值
    return (t) ? t : null;
};

YAHOO.widget.TreeView.counter,这个也是私有属性,用来给TreeView生成一个唯一的ID,
generateId: function(el) {
        var id = el.id;
        if (!id) {
            id = "yui-tv-auto-id-" + YAHOO.widget.TreeView.counter;
            ++YAHOO.widget.TreeView.counter;
        }
        return id;
    },

这个属性的值同样是递增的,generateId方法生成的Id,在TreeView的init方法中就直接赋值给Treeview实例。
    说到TreeView的init方法,我们就仔细看看它做了什么。
init: function(id) {
        this.id = id;
        if ("string" !== typeof id) {
            this._el = id;
            this.id = this.generateId(id);//通过YAHOO.widget.TreeView.counter生成
        }
        this.createEvent("animStart", this);
        this.createEvent("animComplete", this);
        this.createEvent("collapse", this);
this.createEvent("collapseComplete", this);
        this.createEvent("expand", this);
        this.createEvent("expandComplete", this);
this._nodes = [];
        // store a global reference
        YAHOO.widget.TreeView.trees[this.id] = this;
        // Set up the root node
        this.root = new YAHOO.widget.RootNode(this);
        var LW = YAHOO.widget.LogWriter;
        this.logger = (LW) ? new LW(this.toString()) : YAHOO;
        this.logger.log("tree init: " + this.id);
    },

    Init方法做的事情很简单,给TreeView分配一个Id,创建一些事件,把TreeView实例加入到YAHOO.widget.TreeView.trees数组中,生成一个RootNode。还记得我们往树上加第一个节点的时候,父节点就是用的这个RootNode,通过treeView.getRoot()这个方法可以取得。
    在上次的那个例子中,最后调用了treeView.draw()来显示树,现在我们看看这个方法的实现:
draw: function() {
        var html = this.root.getHtml();
        this.getEl().innerHTML = html;
        this.firstDraw = false;
    },

    this.root.getHtml()这个方法通过RootNode的getHtml得到节点的Html表示,this.getEl(),取得TreeView对应Div的对象,然后设置innerHTML。
    TreeView类的介绍就到这,TreeView还有很多控制相关的方法,比如expand,collpase(),removeChildren(),getNodeByIndex()等等,这些方法实现都比较简单,而且不知道他们的实现对使用也没有什么影响,所以就不对这些方法做具体的介绍,有兴趣可以自己查看源码。
    下面要说的是几个以Node结尾的类,先从顶层的YAHOO.widget.Node开始。
YAHOO.widget.Node = function(oData, oParent, expanded) {
    if (oData) { this.init(oData, oParent, expanded); }
};
……….
init: function(oData, oParent, expanded) {
        this.data       = oData;
        this.children   = [];
        this.index      = YAHOO.widget.TreeView.nodeCount;
        ++YAHOO.widget.TreeView.nodeCount;
        this.expanded   = expanded;
        this.logger     = new YAHOO.widget.LogWriter(this.toString());
        this.createEvent("parentChange", this);
if (oParent) {
            oParent.appendChild(this);
        }
},
………


    上面这个是构造函数和Init方法,生成一个Node需要三个参数,第一个oData,这个属性可以是任意类型的,可以是Object,这一点很重要,以后扩展树的时候可以传入你定义好的数据。第二个属性是oParent,就是你构造这个节点的父亲,值可以是树上的其他节点,第三个属性expanded,有true和false两个值,true的时候默认节点展开,false的时候不展开。
    Init方法做一些初始化工作,this.index = YAHOO.widget.TreeView.nodeCount;这个是给每个Node一个唯一Id,之前介绍TreeView类的时候有说到YAHOO.widget.TreeView.nodeCount这个属性。This.children用来存储它的所有子节点,最后oParent.appendChild(this);把新生成的Node加入到oParent的children数组中。
    下面把构造的过程画一张图 (图中的椭圆为属性):

我把余下的方法进行了下简单的分类便于大家理解掌握
/*插入节点的方法*/
appendTo(parentNode) {
        return parentNode.appendChild(this);
    }//很常用的插入节点的方法 但被插入到了参数节点子节点的最后一个
insertBefore: function(node)
     如果这个节点在一个树里则先从这棵树里把该节点删除(注意:appendTo可没有删)
     然后获取参数Node父节点的孩子列表以及该参数Node的位置以此操作该孩子列表在参数节点的位置前面添加
     实现添加。然后重定向该节点和参数Node的前后sibling属性
     最后一步 调用applyParent()方法 重设depth同时也把自己的子节点也引过来了
insertAfter: function(node)
     机理同上 只在第二步操作的位置不一样罢了

/*几个获取ID的方法*/
getElId() 返回这个节点容器div的id  id结构:"ygtv" + this.index
getChildrenElId() 返回节点的Children节点DIV的id 注意是所有子节点在一个DIV里  id结构 "ygtvc" + this.index;
getToggleElId()   返回节点的toggle的id   id结构:"ygtvt"+ this.index  toggle区域就是 树种节点的左边的+ -号的区域
*这些个方法都对应有通过id获取到对象的方法 getEl() getChildrenEl() getToggleEl()

/*节点的收起展开*/(可以添加一些自定义的事件)
collapse() 隐藏起子节点(如果有必要的话可创建子节点)
           核心是:一堆判断之后 调用 this.hideChildren()方法 此方法即获取孩子区域的对象将其display属性设为none
           当然了,也调用了this.updateIcon()方法 此方法用于更新了左边的+ -显示
expand(boolean)     显示子节点 核心:也是一堆的判断 之后调用this.showChildren() 此方法即获取孩子区域的对象将其display属性设为""
expandAll() 和 collapseAll() 很显然 这两个方法是同时展开或收起所有节点以下的节点

/*这个跟动态加载相关*/
setDynamicLoad(fnDataLoader, iconMode) 设置第一次展开节点时动态加载子节点数据的方法 获取方法通过参数fnDataLoader传递给节点的dataLoader属性  fnDataLoader方法的参数  第一个是Node节点类型 第二个是回调函数 如果不设置回调函数的话 在第一次加载之后节点  会关闭动态生成(即设dynamicLoadComplete为true )因为你不指定的话 会调用默认的
setDynamicLoad()第二个参数可选 int型  会赋给iconMode属性(具体用途见前面的属性解析)

/*这个很重要跟自定义节点有关*/
getNodeHtml()   这个方法被设计用来被重写的 本身返回空字符串 以便支持不同种的Node. 方法会在生成节点的时候把取得的html写入节点,从而产生了各种不同的节点样式
getHtml()  这个方法= getNodeHtml()+getChildrenHtml()
getChildrenHtml() 在构建树的时候会被调用 我们总是先构建装子节点的div 但并不提供进去信息 除非这个节点被展开
refresh()  将节点getHtml()获得的html写入到子节点的区域里

getStyle() 获取节点应有的左边+ -号状态 updateIcon()方法会调用
isRoot() 返回节点是否为根节点
isChildOf(parentNode) 获取该节点在父节点的孩子节点列表中的位置 insertBefore/insertAfter方法第二步调用了该方法我自己测试的从0开始。
getSiblings() 返回所有的兄弟节点 包括节点自己
isDynamic() 返回节点的子节点是否应该是被动态生成的 
getAncestor: function(depth) 返回节点某一深度的祖先

    YAHOO.widget.Node就介绍到这,接下来看看继承自YAHOO.widget.Node的其他Node。YAHOO.widget.RootNode的源码如下:
YAHOO.widget.RootNode = function(oTree) {
	this.init(null, null, true);
	this.tree = oTree;
};
YAHOO.extend(YAHOO.widget.RootNode, YAHOO.widget.Node, {
    
    // overrides YAHOO.widget.Node
    getNodeHtml: function() { 
        return ""; 
    },

    toString: function() { 
        return "RootNode";
    },

    loadComplete: function() { 
        this.tree.draw();
    },

    collapse: function() {},
    expand: function() {}

});

    很简单的实现,从构造函数来看,就是给RootNode指定一个tree属性。其Init方法都基本传入的是null,调用YAHOO.widget.Node的Init方法。getNodeHtml返回””,就是说RootNode不能显示出来,是一个隐藏的节点。其他几个方法的实现都很简单,不用多说。
    YAHOO.widget.HTMLNode继承自YAHOO.widget.Node,看源码可以发现HTMLNode多加了三个属性,构造函数也加了一个属性,叫hasIcon,这个属性是用来控制是否要显示树前面的那些加号、减号以及虚线等图标的。
YAHOO.widget.HTMLNode = function(oData, oParent, expanded, hasIcon) {
    if (oData) { 
        this.init(oData, oParent, expanded);
        this.initContent(oData, hasIcon);
    }
};

YAHOO.extend(YAHOO.widget.HTMLNode, YAHOO.widget.Node, {
	contentStyle: "ygtvhtml",
contentElId: null,
html: null,	

增加的三个属性分别是:
    contentStyle: "ygtvhtml",设置显示的CSS样式
    contentElId: null,给Content Element设置一个ID
    html: null,用来显示的Html内容
它重写的方法有toString(),getNodeHtml(),getNodeHtml()是节点显示的主要方法。
它增加的方法有initContent: function(oData, hasIcon),setHtml: function(o),这些方法的实现都很简单,不用详细说明。
    YAHOO.widget.TextNode是比较常用的一种Node,它根据你传入的oData来构造显示,如果传入的oData是String,则把String当作Label显示出来,如果传入的是Object,则根据Object的label属性来显示,同时还可以给Object设置style,title等属性,可以很灵活的控制节点要显示成什么样,要显示哪些信息。
    具体的显示它重写了getNodeHtml()方法。新加了onLabelClick方法,在点击树节点的Label的时候触发。
    最后是YAHOO.widget.MenuNode ,它继承自YAHOO.widget.TextNode,只从写了toString()方法。
   
    通过分析上面几个继承自YAHOO.widget.Node的Node,可以发现实现一个Node很简单,在init方法里面加入一些新的操作,加入一些新的属性,最后重写一些方法,就能得出符合自己要求的Node。YUI在Node的设计上做得是相当不错的,给了我们很方便的方法来扩展已有的Node。下一次我将会详细的讲解如何构建满足自己需求的Node。




分享到:
评论

相关推荐

    YUI 入门教程YUI 入门教程YUI 入门教程

    YUI教程YUI 入门教程YUI 入门教程YUI 入门教程

    YUI3 中tree的两种实现

    NULL 博文链接:https://ttwang.iteye.com/blog/1741631

    基于yui的layout,tree的demo

    基于yui的layout,tree的一个demo

    yahoo yui 实例教程

    利用Yahoo YUI库做的一个TREE实例,很详细的阐述了YUI的使用原理

    yuicompressor-yui compressor

    yuicompressor-2.4.2.jar yuicompressor-2.4.7.jar jsZip.exe yuicompressor yui compressor js压缩工具 javascript压缩工具 css压缩工具 ------------------------------------ //压缩JS java -jar yui...

    YUI中文文档CHM

    YAHOO YUI 中文文档 AJAX 详细 比较好用

    yui_2.9.0前端UI

    YUI 库,全称Yahoo! UI Library。是一组工具和控件,用JavaScript写成, 为的是用DOM 脚本,DHTML和AJAX等技术创建丰富的网页交互式应用程序。 YUI 基于BSD协议,对所有的使用方式都是免费的。YUI 项目包括YUI 库和两...

    YUI 详细说明文档

    好东西啊,想学习yui一定要看看。我当初学这个费好大的力气呢

    yui3-master.zip

    yui3-master.zip

    yuitest YUI测试工具

    YUI Test is a complete testing framework for JavaScript and Web applications. You can use the simple JavaScript syntax to write unit tests that can be run in web browsers or on the command line, as ...

    YUI Compressor压缩JS和Css工具(包含详细配置)

    YUI Compressor压缩JS和Css工具,可对js以及css进行压缩、合并、打包,并包含详细工具使用配置说明,如果你一个web前端开发工程师你值得拥有!

    yui_2.6.0r2

    yui_2.6.0r2 yui_2.6.0r2 yui_2.6.0r2 yui_2.6.0r2 yui_2.6.0r2

    从YUI2到YUI3看前端的演变 pdf

    现场有很多人提出疑问,大家无非关心的是“效率”二字。个人以为在现阶段,这种方式有一点激进,否能为广大用户所接受并发扬光大,还需要时间检验。YUI是个“学院派”的框架,以性能和严谨著称,易用性相对而言弱了...

    yui详细教程,适合新人

    yui详细教程,适合新人yui详细教程,

    YUI3 dialog组件

    基于YUI3的dialog组件该组件是基于YUI3开发的,功能强大,详细见http://www.qiqicartoon.com

    雅虎YUI组建

    雅虎YUI组件,内附详细实例

    yui 资源包

    yui 源码下载,3.9.0 r2 包,最新版本

    yuicompressor,给YUI Compressor添加右键命令

    YUI Compressor非常好用,特别是JS的混淆是众多JS Coding的最爱。可惜官网提供的版本都不具备右键功能,每次压缩都要cmd输入一些命令实在是繁琐,本文就介绍如何给YUI Compressor添加右键命令,方便使用。 网上已有...

    js 压缩YUI

    雅虎的东西,简单的操作很好用 使用例子:java -jar D:\yuicompressor\yuicompressor\yuicompressor.jar E:\js\all.js -o E:\wap\wap2\js\all-min.js --charset utf-8 当然要装jdk了 不然就玩完了

    yui压缩

    yui压缩

Global site tag (gtag.js) - Google Analytics