翻译 - 【Dojo Tutorials】Creating Template-based Widgets

原文:Creating Template-based Widgets

在本教程中,你将学习Dijit的_TemplatedMixin混入类的重要性与如何利用模版快速创建你自己的自定义挂件。

开始

如果你不熟悉如何创建Dijit挂件,你也许需要想看看理解_Widgets教程创建自定义挂件教程编写你自己的挂件教程也或帮助你学习如何创建挂件。

Dijit的_WidgetBase为创建挂件提供了优秀的基础架构,但是_TemplatedMixin混合类才是Dijit闪耀的所在。使用_TemplatedMixin和_WidgetsInTemplateMixin,你可以快速的创建可维护,快速修饰的挂件。

_TemplatedMixin的基础概念非常简单:它允许开发者创建一份有些小扩展的HTML文件,在运行的时候载入它并提供给挂件实例来使用。

让我们来看看_TemplatedMixin都定义了些什么(以及为什么),与使用它的功能如何构建一个简单的挂件。

注意_TemplateMixin意在作为混入类使用,不会直接用于继承。在基于类的语法中,它更像是接口(尽管在JavaScript中接口和类傻傻分不清)。在Dojo中类是如何工作的,请看Dojo声明教程

_TemplatedMixin提供了些什么

_TemplatedMixin为挂件提供了一个templateString属性,看起来十分简单,为什么如此强大的东西就这么点呢?答案就在于除此之外_TemplateMixin给你的挂架还添加了些什么。

小贴士:templatePath还存在,但不在用于载入模版了,它依然在那儿是为了向后兼容。后面我们会看到如何使用dojo/text!来载入挂件的模版。

重载方法

除了上面提到的属性外,_TemplateMixin重载了Dijit挂件架构中定义的两个方法:buildRendering和destroyRendering。这两个方法处理解析与填充模版(buildRendering)和适当的销毁挂架的DOM(destroyRendering)。

因为这两个方法都是处理模版的,如果你重载了任意一个都记得要通过this.inherited(arguments)来调用父类方法。可以查看Understanding _WidgetBase Tutorial来了解挂件生命周期的更多细节。

使用_TemplatedMixin

为了使你的挂件“模版化”,只需要在你挂件的声明继承数组的第二或后续位置中添加djijit/_TemplatedMixin即可。例如,可以这样来声明一个挂件:

 1 define([
 2     "dojo/_base/declare",
 3     "dijit/_WidgetBase",
 4     "dijit/_TemplatedMixin",
 5     "dojo/text!./templates/SomeWidget.html"
 6 ], function(declare, _WidgetBase, _TemplatedMixin, template) {
 7 
 8     return declare([_WidgetBase, _TemplatedMixin], {
 9         templateString: template
10     });
11 
12 });

Dijit遵从一个创建目录的标准,在模块所在目录中创建templaltes目录,建议你也遵从此规范。

你可能注意到我们结合通过dojo/text!{path}载入的模版使用了templateString属性。这是使用模版文件的建议方式,确保在创建一个Dojo工具的时候可以异步载入且适当的集成。

现在我们已经有了基于模版的挂件,让我们来写一个模版,来看看它提供了那些可用的钩子(hook)。

写模版

一个模版是在你定义一个DOM结构中的一个HTML文档片段,结合任何特殊的“钩子”绑定进你的挂件定义。让我们看一个快速的例子,在植入每个钩子之前,如何在模版中替换变量。这里是我们上面的挂件模版:

1 <div class="${baseClass}">
2     <div class="${baseClass}Title" data-dojo-attach-point="titleNode" data-dojo-attach-event="onclick:_onClick"></div>
3 </div>

虽然简单,这个模版演示了Dijit模版系统的三个重要方面:变量替换,附着点,事件附件。

当你定义一个模版的时候,它只能有一个顶级节点。多个顶级节点是不允许。

变量替换

一个模版可以拥有了变量集合用于DOM渲染,通过使用简单的变量占位符语言,看起来像这样:

1 ${property}

变量名称是一个在挂件中定义的属性或字段;上面的例子使用了属性baseClass,但是对于实例的自定义字段也很好,如果我们在挂件中定义了一个属性foo,我们可以在模版中使用${foo}。如果在属性是一个引用对象的时候,你想要使用这个对象的属性,你可以通过对象引用符号:

1 ${propertyObject.property}

为了避免字符串被转义,可以在变量名前添加!,像这样:

1 ${!property}

模版中的变量替换只建议使用那些在挂件生命周期中不会变化的属性。也就是说,如果你期望一个能够在挂件中设置的属性值,我们建议你在postCreate方法中使用get方法。

附着点

Dijit模版系统有一个特殊的属性,它将查找你模版中叫做附着点的东西,使用HTML5的data属性语法来实现的。当一个定义有data-dojo-attach-point属性的DOM元素被创建时,附着点告诉模版渲染器去设置属性的值作为固件的属性名,值为被创建的DOM元素。例如,挂件有两个节点(像上面的那样)。主元素可以在挂件使用domNode属性来引用,内部的div在代码可以使用titleNode来引用。

containerNode附着点

Dijit还定义了一个“魔术”附着点叫做containerNode。容器节点的基本概念是提供一个添加标记的地方,如果挂件是声明定义的。如:

1 <div class="${baseClass}">
2     <div class="{$baseClass}Title" data-dojo-attach-point="titleNode" data-dojo-attach-event="ondijitclick:_onClick"></div>
3     <div class="${baseClass}Container" data-dojo-attach-point="containerNode"></div>
4 </div>

我们在标记声明中可以这样使用:

1 <div data-dojo-type="demo/SomeWidget" data-dojo-props="title:'Our Some Widget">
2     <p>This is arbitrary content!</p>
3     <p>More arbitrary content</p>
4 </div>

当Dojo解析器遍历文档时,它将发现我们的示例挂件并实例化它——作为实例化的一部分,挂件中的任何标记都将附加到containerNode中。所以当挂件启动并完成后,它的DOM看起应该是这个样子:

1 <div id="demo_SomeWidget_0" class="somWidgetBase">
2     <div class="somWidgetTitle">Our Some Widget</div>
3     <div class="somWidgetContainer">
4         <p>This is arbitray content!</p>
5         <p>More arbitray content!</p>
6     </div>
7 </div>

为了简洁我们移除了一些自定义的属性;Dijit在实际渲染的时候是不会移除它们的。

事件附件

除了附着点,Dijit模版系统为自定义挂件提供了一种关联原生DOM事件的方式。通过HTML5属性data-dojo-attach-event来完成。在(由冒号分隔的)键值对之间有一个逗号;键是处理器附着的原生事件,值是当时间发生时调用的挂件方法的名称。如果只有一个时间需要处理,省略逗号。例如,在Dijit的MenuBarItem中定义的属性data-dojo-attach-point:

1 data-dojo-attach-event="onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick"

当你的挂件被实例化,模版的DOM片段被创建后,Dijit模版系统将遍历附着事件,为挂件对象和DOM绑定时间监听——这让你在控制器代码中操纵视图变得无比简单。另外,当事件触发时,原生事件处理器的参数或传递到挂件处理器中,所以你可以完全知道浏览器发生了什么。

另外,我们想要使用dijit/_OnDijitClickMixin添加到修改事件中,它比原生的onclick事件提供了更多的功能。因此我们需要修改我的挂件定义:

 1 define([
 2     "dojo/_base/declare",
 3     "dijit/_WidgetBase",
 4     "dijit/_OnDijitClickMixin",
 5     "dijit/_TemplatedMixin",
 6     "dojo/text!./templates/SomeWidget.html"
 7 ], function(declare, _WidgetBase, _OnDijitClickMixin, _TemplatedMixin, template) {
 8 
 9     return declare([_WidgetBase, _OnDijitClickMixin, _TemplatedMixin], {
10         tempalteString: template
11         // any constom code goes here
12     });
13 
14 });

我们还需要修改模版:

1 <div class="${baseClass}">
2     <div class="${baseClass}Title"
3         data-dojo-attach-point="titleNode"
4         data-dojo-attach-event="ondijitclick:_onClick"></div>
5     <div>And our container:</div>
6     <div class="${baseClass}Container"
7         data-dojo-attach-point="containerNode"></div>
8 </div>

_WidgetsInTemplatedMixin混入类

最后,Dijit的模版系统允许你使用_WidgetsInTemplatedMixin通过模版创建更灵活的挂件。这个混入类告诉模版系统你的挂件中有别的挂件在其中,当实例化你的挂机时,它内部的挂件也会被实例化。

例如,让我们改一些我们的定义包含一个Dijit按钮:

 1 define([
 2     "dojo/_base/declare",
 3     "dijit/_WidgetBase",
 4     "dijit/_OnDijitClickMixin",
 5     "dijit/_TemplatedMixin",
 6     "dijit/_WidgetsInTemplateMixin",
 7     "dijit/form/Button",
 8     "dojo/text!./templates/SomeWidget.html"
 9 ], function(declare, _WidgetBase, _OnDijitClickMixin, _TemplatedMixin,
10             _WidgetsInTemplateMixin, Button, template) {
11  
12     return declare("example.SomeWidget", [_WidgetBase, _OnDijitClickMixin,
13         _TemplatedMixin, _WidgetsInTemplateMixin
14     ], {
15         templateString: template
16         //  your custom code goes here
17     });
18  
19 });

我们模版建成这样的:

1 <div class="${baseClass}" data-dojo-attach-point="focusNode"
2         data-dojo-attach-event="ondijitclick:_onClick"
3         role="menuitem" tabIndex="-1">
4     <div data-dojo-type="dijit/form/Button"
5         data-dojo-attach-point="buttonWidget">
6         My Button
7     </div>
8     <span data-dojo-attach-point="containerNode"></span>
9 </div>

注意我们修改的模版,我们在按钮标记中添加一个叫做buttonWidget附着点。这是Dijit附着点系统的额外奖励;因为是我们定义了一个挂件,将它作为属性添加到我们的挂件中,myWidget.buttonWidget将引用这个实际的按钮挂件而不是DOM节点。这允许你使用简单的构建块创建最优的挂件,如展示email列表的挂件,带有预设挂件的工具条等等。

当然,你需要引入你模版中使用的挂件模块文件。你不能使用Dojo1.8的自动载入功能,因为创建过程是同步的而自动载入是异步的。

除非你有明确的意向在模版中定义挂件,否者不要使用dijit/_WidgetsInTemplatedMixin。使用过渡会造成性能为题。

总结

在本教程中,我们学习了通过混入类_TemplatedMixin和_WidgetsInTemplatedMixin类实现我们强大的Diji模版系统,与如何在你的应用利用这个系统快速创建自定义挂件。我们复习了如何使用模版的附着点与时间附件允许你快速的绑定事件到你的代码,如何在模版中替换变量,如何通过在模版中包含其他挂件来创建最优挂件。

posted on 2014-10-29 11:21  古道倦马  阅读(447)  评论(0编辑  收藏  举报

导航