Dojo所开发的控件具有很强的内聚性和面向对象性。dojo的dijit._widget是dojo提供的图形界面组件库。
首先从dijit组件的核心类dijit._Widget开始。dijit._Widget是所以dijit组件的父类,dijit默认提供的组件和自己开发的组件都要继承此类。dijit._Widget提供了对组件生命周期的管理。dijit组件生命周期管理在实现的时候使用了
template method设计方式。dijit._Widget的create()方法定义了默认模版。开发人员也可以覆盖create()方
法,提供一套不同的生命周期实现。dijit定义的生命周期实现:
图中椭圆行的三个方法是dijit提供的扩展点,用户可以自己覆盖这些方法。startup方法需要显示被调用。
组件的connect()绑定事件处理方法。subscribe()监听事件通知。
另外一个核心类:dijit._Templated
上面提到用buildRendering()创建用户界面,如果通过DOM操作创建的话比较复杂,dijit._Template提供了一种从HTML模版中创建用户界面的方式。dijit._Templated是作为一个混入类来使用的。在dojo.declear()定义新组件的时候,dijit._Widget需要作为基类,而dijit._Templated要作为混入类,也就是说在父类声明中dijit._Widget需要作为第一个出现,否则会出错。
可以通过templateString 和templatePath两种方式指定使用的模版。
可以通过设定widgetInTemplate的值为true来声明该dijit组件包含其他组件。这些包含的组件在destroy方法中被销毁。
在模版中可以使用dojoAttachPoint和dojoAttachEvent两个特殊的DOM节点属性。dojoAttachPoint属性的值是当前DOM节点,dojoAttachEvent属性的值来完成事件处理绑定。
下一个核心类dijit._Container:
dijit._Container提供了管理子组件的功能。它所提供的方法有:
addChild(widget,insertIndex);
removeChild(widget);
getChildren():包含子组件的数组。
hasChildren()是否包含子组件。
getIndexOfChild();
需要注意:dijit._COntianer只能包含dijit组件,也就是必须继承子dijit._Widget,不能包含普通的DOM组件。对于DOM节点可以用dijit.layout.pane封装之后,再添加到dijit._Container中。
下面介绍如何对dijit组件进行管理:
DOJO会负责维护当前页面上所有dijit组件的一个注册表。里面包含了所有的dijit组件对象,可以通过dijit.registry来访问,它是一个dijit.WidgetSet类的实例。dijit.WidgetSet实际上是一个dijit组件的对象表。通过ID可以查到组件对象。它提供的方法有:
add(widget);remove(id);byId(id);byClass(cls);
dijit.registry.byClass("dijit.form.Button")返回页面上所以的dijit.form.button组件,返回的是一个新WidgetSet对象。
toArray()返回包含所有组件对象的数组。
forEach(),filter(),map(),every(),some(),这些与dojo基本库方法是相同的。
在管理组件的时候需要注意ID的重复。
在介绍完dijit组件管理之后,下面介绍实例化dijit组件的两种方法
实例化有两种方式,声明式和编程式。
声明式是指在HTML代码中以描述的方式来定义dijit组件,由dojo运行时把这些声明的这些组件实例化。编程式的方式是在代码中以显示的new来实例化。实例化一个dijit组件需要两个参数,第一个是混入到组件实例中的包含配置属性的javascript对象,第二个参数则是组件所使用的DOM节点。这两个方式的不同在于如何提供者两个参数值。实例见http://topic.csdn.net/u/20090623/18/db85bb51-9d79-4e2a-bc6d-97a6d200503c.html
组件生命周期
组件的生命周期指的是某一个组件从创建到销毁的存续阶段。理解在各个阶段被调用的函数有助于自定义组件或继承组件的功能扩展。
constructor():
构造函数,在使用new操作时被调用,发生在参数被混合进组件实例之前,主要用于状态、属性的初始化。
参数被混合进组件实例:
如果使用标签化实现或编程实现来实例化一个组件类的时候,传入参数,比如<button dojoType="dijit.form.Button" iconClass ="">或new dijit.form.Button({iconClass: ""}),该阶段没有关联特殊的函数,但我们可以使用传入的这些参数值。
postMixInProperties()自定义属性:
使用自定义属性,如果在你的widget里面需要自定义属性。该函数会在该组件对应DOM节点创建前被调用。可以通过参数传入一个包含各种属性的javascript对象,这些属性被混入到dijit组件中,可以通过this调用。当混入完成之后,在创建dijit组件界面之前,还可以加入自己的业务。
buildRendering()创建其外观:
该方法用来创建dijit组件的用户界面,即DOM节点,该方法完成时候,this.domNode指向的是刚创建的DOM节点。
postCreate()快速创建:
被自定义组件经常使用的一个函数。当DOM节点被创建完成之后,此方法被调用。需要注意的是,这个时候组件的DOM节点还没有被添加到当前页面文档树。一般用来添加添加组件相关的逻辑。
startup()如果要创建一个孩子widget:
在建立了一个父组件后,还需要添加若干子组件(这里的子组件不是表示继承关系,而是表示包含关系),并希望全部加载后一起展现时,就可以调用该函数。
一个关于该函数的最佳实践就是即使没有子组件,也对一个组件新建实例调用该函数,
destroy():
dijit组件的销毁过程比较复杂。组件实例的销毁,占用资源的释放。包括该组件的DOM节点,类似C语言里的析构函数。dijit._Widget提供了多个以destroy为前缀的方法,如destroyRecursive()用于某组件以及其内部包含的子组件(这里的子组件含义同startup处的说明)的销毁。
小提示:
在某个函数需要覆盖的所有情况下,都继承执行父类的该函数,形如:
postCreate: function() {
this.inherited("postCreate", arguments);
}