Dojo学习笔记——创建基于模板的部件

来源:互联网 发布:人工智能猜人 编辑:程序博客网 时间:2024/04/29 13:51

难度:中级 Dojo版本:1.8
原文:http://dojotoolkit.org/documentation/tutorials/1.8/templated/

开始
Dijit的_WidgetBase为创建小部件提供了一个极好的基础,但是其真正的闪光点是_TemplatedMixin混入类。使用_TemplatedMixin_WidgetsInTemplateMixin,可以快速的创建高度可维护,快速可修改和易操作的小部件。
_TemplatedMixin的基本概念很简单,允许开发者创建有一些小扩展的小的HTML文件,在运行时或是嵌在构建过程中作为一个字符串加载该HTML文件,为模板部件的所有实例所复用。
注意_TemplatedMixin旨在用于混入,而非直接继承。在基于类的语法中,这意味着更像一个接口而非类,虽然在JavaScript中两者之间区别很模糊。

_TemplatedMixin提供什么
对于开发者,将_TemplatedMixin混入一个部件的定义在部件上提供了以下的附加属性:
templateString // a string representing the HTML of the template
注意此时也加入了templatePath,但不再用于模板加载。其为了向后兼容依然存在。

覆写方法
除了上述的属性外,_TemplatedMixin覆写了两个在Dijit的部件构架中的方法,buildRenderingdestroyRendering。这两个方法处理了模板的解析和填写,以及部件的DOM的正确销毁。
这两个方法对于模板过程至关重要,务必要在覆写的方法中通过加入this.inherited(arguments)包含对父版本的调用。

使用_TemplatedMixin
使得定制的部件模板化,所有需要做的就是在类声明数组中加入dijit/_TemplatedMixin作为第二个或是之后的参数。例如声明一个SomeWidget部件:
define(["dojo/_base/declare","dijit/_WidgetBase","dijit/_TemplatedMixin","dojo/text!./templates/SomeWidget.html"], function(declare, _WidgetBase, _TemplatedMixin, template) {return declare([_WidgetBase, _TemplatedMixin], {templateString: template// your custom code goes here});});
Dijit遵循一个建立一个称为templates的单独目录的标准,和JavaScript声明位于相同的层次,建议编码时遵守该标准。
注意在以上极为简单的声明中,使用了templateString属性,和经由dojo/text!{path}加载的模板相互协调。这是给模板文件设置引用的推荐方式,确保了当创建Dojo Toolkit的一个结构时文件可以异步和完全集成的加载。

写模板
模板是一个HTML文档片段,其中定义了一个DOM结构,以及任何特殊的和部件声明联系的hooks。这是一个假定的SomeWidget模板:
<div class="${baseClass}"><div class="${baseClass}Title" data-dojo-attach-point="titleNode"data-dojo-attach-event="onclick:_onClick"></div></div>
这个模板演示了Dijit模板系统三个最重要的方面:变量替换,附加点和事件附加。
注意定义模板时,只能定义一个根节点,如同XML文档。

变量替换
模板可以有值在DOM渲染时设置,使用了一个简单的变量占位符语法,如${property}
变量名为在部件声明中定义的任意属性或字段。以上例子使用了属性baseClass(任何部件具有),但是和自定义字段一样工作,例如在SomeWidget中定义了一个属性称为foo,只要在模板中简单的使用${foo}。若属性刚好是对一个对象的引用,想要使用该对象中的属性值,可以使用普通的对象引用标识${propertyObject.property}
为防止在字符串中_TemplatedMixin的转义引证,可以在全变量名前加!,如${!property}
模板中的变量替换只推荐在部件的生命周期里值不改变的时候使用,也就是说,若希望能够在部件的生命周期里以编程的方式设置属性的值,则推荐使用部件的postCreate方法通过部件的set()方法以编程的方式设置任何变量。

附加点
Dijit的模板系统有一个在模板中寻找的特殊属性称为附加点,使用HTML5的数据属性语法实现。当使用data-dojo-attach-point属性定义的DOM元素被创建,附加点通知模板渲染器设置该属性的值,作为部件的性质,为对所创建DOM元素的引用。例如,SomeWidget模板定义了两个DOM元素,主元素(外部div)可以通过性质domNode在代码中引用,内部div元素可以通过性质titleNode在代码中引用。
通常,模板的根节点成为部件的domNode性质,一般定义中不会包含一个附加点属性。然而有时模板中允许根节点也和其它子系统作用,如Dijit的焦点管理。

containerNode附加点
Dijit也定义了一个称为containerNode的附加点,这容器节点的基本概念是若以声明的方式创建部件,提供一些任何额外的标记去放置。例如:
<div class="${baseClass}"><div class="${baseClass}Title" data-dojo-attach-point="titleNode"data-dojo-attach-event="ondijitclick:_onClick"></div><div>And our container:</div><div class="${baseClass}Container"data-dojo-attach-point="containerNode"></div></div>
可以像这样在声明式标记中使用:
<div data-dojo-type="demo/SomeWidget"data-dojo-props="title: 'Our Some Widget'"><p>This is arbitrary content!</p><p>More arbitrary content!</p></div>
当Dojo解析器遍历文档,找到示例部件加以实例化,作为实例的一部分,任何在部件中的标记将被追加到containerNode。因此当部件启动完成时,结果DOM如下:
<div id="demo_SomeWidget_0" class="someWidgetBase"><div class="someWidgetTitle">Our Some Widget</div><div class="someWidgetContainer"><p>This is arbitrary content!</p><p>More arbitrary content!</p></div></div>
注意为了简洁移除了一些定制的属性,当Dijit渲染模板时不会移除。
也要注意若在主标记中嵌入了其它小部件定义,部件有containerNode附加点,任何部件将实例化到容器节点内。例如,以下为典型的组装应用情景:
<div data-dojo-type="demo/SomeWidget"><p>This is arbitrary content!</p><div data-dojo-type="dijit/form/Button">My Button</div><p>More arbitrary content!</p></div>

事件附加
Dijit模板系统给予了一种方式,附加本地DOM事件到定制部件的方法中,通过使用HTML5的data-dojo-attach-event属性实现。这是一个逗号分隔的键值对字符串(用冒号分开),键是连接到处理方法的本地DOM事件,值是当事件触发时部件要执行的方法的名字。只有处理单个事件时,忽略尾部的逗号。例如,在Dijit的MenuBarItem中定义的dojo-data-attach-event属性:
data-dojo-attach-event="onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick"
当部件实例化,DOM片段从模板创建,Dijit模板系统遍历任何附加事件定义,从结果DOM和部件对象自动关联这些事件(使用dojo/on),使得关联可视的表征到控制代码极其简单。另外,当这些事件处理触发,通常使用本地DOM事件机制传递的相同的参数将传递给部件处理程序,以便可以完全的访问浏览器的报告内容。
而且可使用dijit/_OnDijitClickMixin,加入一个修改事件,比标准的DOMonclick事件支持更多的功能。因此需要修改部件定义:
define(["dojo/_base/declare","dijit/_WidgetBase","dijit/_OnDijitClickMixin","dijit/_TemplatedMixin","dojo/text!./templates/SomeWidget.html"], function(declare, _WidgetBase, _OnDijitClickMixin, _TemplatedMixin,template) {return declare([_WidgetBase, _OnDijitClickMixin, _TemplatedMixin], {templateString: template// any custom code goes here});});
还需要修改部件模板:
<div class="${baseClass}"><div class="${baseClass}Title"data-dojo-attach-point="titleNode"data-dojo-attach-event="ondijitclick:_onClick"></div><div>And our container:</div><div class="${baseClass}Container"data-dojo-attach-point="containerNode"></div></div>
查看示例

_WidgetsInTemplateMixin混入
Dijit模板系统允许从模板创建更加复杂的部件,通过使用_WidgetsInTemplateMixin混入。这通知模板系统,模板有着其它模板在其中,当部件实例化时实例化它们。
例如,修改声明使得总是包含一个Dijit按钮:
define(["dojo/_base/declare","dijit/_WidgetBase","dijit/_OnDijitClickMixin","dijit/_TemplatedMixin","dijit/_WidgetsInTemplateMixin","dijit/form/Button","dojo/text!./templates/SomeWidget.html"], function(declare, _WidgetBase, _OnDijitClickMixin, _TemplatedMixin,_WidgetsInTemplateMixin, Button, template) {return declare("example.SomeWidget", [_WidgetBase, _OnDijitClickMixin,_TemplatedMixin, _WidgetsInTemplateMixin], {templateString: template// your custom code goes here});});
可以创建如下模板:
<div class="${baseClass}" data-dojo-attach-point="focusNode"data-dojo-attach-event="ondijitclick:_onClick"role="menuitem" tabIndex="-1"><div data-dojo-type="dijit/form/Button"data-dojo-attach-point="buttonWidget">My Button</div><span data-dojo-attach-point="containerNode"></span></div>
注意在修改的模板中,连同按钮的标记加入了一个称为buttonWidget的附加点。这是Dijit的附加点系统的额外奖励,因为考虑中的定义为一个部件,部件myWidget.buttonWidget的添加性质为对实际按钮部件的引用,而不是对DOM元素的引用。这允许用简单的积木创建uber-widgets,例如查看电邮列表的部件,有预设部件的工具栏,以及更多。
注意应当将任何模板使用到的部件请求入模块中,不能在部件模板中利用dojo/parser的自动请求特征,因为创建的生命周期是同步的而自动请求特征是异步运行。
注意除非在模板中有明确的需要,不要混入dijit/_WidgetsInTemplateMixin。如果过度使用,其引发时的额外开销会影响部件和应用的性能。
原创粉丝点击