Dojo 1.6 官方教程翻译:创建基于模板的小部件(Widget)

创建 基于模板的小部件(Widget)

作者:Tom Trenka

原文链接:http://dojotoolkit.org/documentation/tutorials/1.6/templated/

译者: feijia (tiimfei@gmail.com)


在本教程中,你将学到Dijit 的重要组成部分模板系统:Dijit._Templated ,以及如何使用模板来快速创建自己的小部件

难度: 中等, 使用Dojo 版本: 1.6



Dijit (Dojo的小部件库)提供的_Widget 和_WidgetBase基类为开发小部件提供了完整的基础类,但是_Templated 基类的所引入的模板系统则使Dijit更显强大和灵活。

使用_Templated , 你可以快速的创建出易于维护,方便修改的小部件。

_Templated 的原理非常简单:它允许开发者创建一小段HTML片段,片段在运行时会被作为字符串加载(或者在build过程中直接内联入代码内)并被所有该小部件的实例所重用。

接下来我们将会解读_Templated 提供了哪些功能,并且动手开发一个使用_Templated 的小部件。

注意:_Templated 应当被当作混入代码使用(mixin), 而不是被直接继承。 用面向对象的观点来看,_Templated 更接近一个接口而不是一个类(虽然在JavaScript中,并没有办法明确区分二者)


_Templated 提供了哪些方法和属性


对使用_Templated 的程序员来说或,将_Templated 混入一个小部件将会给这个小部件的类带来下列的新属性:

templateString,// a string representing the HTML of the template
templatePath,// a URL pointing at a file to be used as a template
widgetsInTemplate // a Boolean indicating whether or not child widgets
// are defined in the template



注意:templatePath 现在已经基本不使用了,只是为了向后兼容而保留。下面的章节中我们会展示如何搭配使用dojo.cache 和 templateString

这些新属性看起来如此简单,那么多强大的功能仅凭这几个属性就能实现么?真正的答案隐藏在_Templated向你的小部件定义中添加的其他内容。

_Templated覆写的方法


除了上述几个属性之外, _Templated覆写了Dijit Widget架构中的三个基础方法:buildRendering,destroyRendering,和startup. 这三个方法分别负责:解析并填充模板(buildRendering),正确销毁Widget DOM树(destroyRendering),并保障模板中包含的子Widget能够正确的被启动(startup)

注意:因为上述三个方法对于使用模板是必须的,如果你在自己的代码中也进一步覆写了这几个方法,请务必在你的覆写代码中加入this.inherited(arguments) 来调用父类的方法确保模板能正确处理。

使用_Templated


你只需要在创建Widget的类声明中的第二个参数数组中加入“dijit._Templated" ,就可以让你的Widget 支持模板. 例如,下面的代码就声明了一个支持模板的名为SomeWidget的Widget


dojo.declare("example.SomeWidget",[ dijit._Widget,dijit._Templated ],{
    templateString: dojo.cache("example","templates/SomeWidget.html")
    //  your custom code goes here
});



Dijit 组件库中的组件都遵循在当前Javascript目录中创建一个单独的名为templates的目录来保存模板的编码习惯。 我们建议你也遵循同样的做法。


注意:在上述声明中,我们搭配使用了dojo.cache 和templateString 属性,dojo.cache方法会从其缓存或url中获取资源。这是最新版dojo中推荐的用来获取资源(例如这里的模板文件)的做法,它确保了使用尽量少的HTTP请求来获取资源.


现在我们已经有了可以支持模板的一个小部件的声明,接下来我们要为它写一个模板,并且解释模板可以包含哪些功能。



创建模板



一个模板就是一个HTML代码片段,你可以在其中定义DOM结构,也可以注入一些特殊的内容。 我们先从一个简单例子看起。

<div class="${baseClass}" data-dojo-attach-point="focusNode" data-dojo-attach-event="ondijitclick:_onClick" role="menuitem" tabindex="-1">
    <span data-dojo-attach-point="containerNode"></span>
</div>



在这个简单的模板里,演示了Dijit模板的3个重要功能:变量的替换,附着点(attach point), 以及DOM事件绑定. 接下来我们会依次解释这三个功能。

注意:每个模板的HTML中只能有一个根节点。 包含多个根节点的模板是非法的。

变量的替换:


模板中可以引用小部件中定义的变量的值。语法很简单

${property}

上述例子中,我们在模板的根节点的class属性里引用了变量baseClass的值(该变量适用于所有Widget). 如果该变量本身是一个对象的话,你还可以进一步引用该对象的属性值。 这时你需要在属性名前加上一个!

如:
${!propertyObject.property}

注意:从Dijit 1.5 开始,模板中使用变量值替换仅限用于哪些在小部件的整个生命周期中都不会变化的那些属性。如果你希望可以在声明周期中修改某属性值,我们建议你在postCreate方法中通过调用set方法来设置。



附着点(Attache Points)


Dijit 模板系统会在你定义的模板中寻找一个特殊的属性(称为attach point) - 使用了HTML5 的数据属性(data-*) 语法。一个连接点告诉模板渲染引擎: 如果模板中的某DOM节点上定义了data-dojo-attach-point 属性,则该节点的引用会被设置为在Widget中的对应属性。例如, 在上面例子中的SomeWidget的模板 定义了2个DOM节点。主节点(外层的div)可以在Widget代码中被引用为focusNode,而内层的span节点则可以通过Widget的containerNode属性来引用。


注意: 通常即使你在模板中不设置任何attach point ,模板的根节点可以在widget中通过domNode来引用。所以大多数时候你用不着显示的使用这个属性。


containerNode 容器节点


Dijit定义了一个特殊的附着点叫做”containerNode" . 从名字可以理解,containerNode就是一个容器节点,它为使用声明(declarative)方式创建的widget提供了放置额外标记片段的地方。例如:
<div data-dojo-type="example.SomeWidget">
    <p>This is arbitrary content!</p>
    <p>More arbitrary content!</p>
</div>



这个片段使用声明的方式创建了我们前面定义的SomeWidget的实例,在Dojo解释器解析这个段落时,它会实例化一个SomeWidget,而实例化的同时在这里被Div包含的HTML片段都会添加到SomeWidget所定义的容器节点中去。 所以当这个Widget被创建后,DOM树的结构会是:
<div class="someClass" role="menuitem" tabindex="-1">
    <span>
        <p>This is arbitrary content!</p>
        <p>More arbitrary content!</p>
    </span>
</div>




注意:上例中为了教程的简洁我们省去了一些自定义HTML5属性。


类似的,如果你在Widget声明中嵌入其他的Widget,那么子Widget也将被添加到你的容器节点中去(前提是你的Widget定义了一个容器节点) . 例如:
<div data-dojo-type="example.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事件绑定到Widget的自定义方法上。这是通过另一个HTML5 自定义数据属性完成的:data-dojo-attach-event 。 该属性值是一组由逗号分割的键值对(键值间用冒号分开),键是原生DOM事件,值是要绑定此事件的Widget中的自定义方法。
例如:

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



这个例子里我们定义的ondijitclick事件是一个Dijit自己定义的稍有改动onclick处理方法,在Dijit里通常可以使用onclick 的地方都可以是用ondijitclick 代替。

当Widget被实例化时,Diji模板系统会自动遍历所有的事件绑定属性,并使用connect 将这些事件和Widget中的方法绑定起来。当DOM事件被触发时,你的事件处理函数将能获得跟原生DOM事件同样多的参数,因此你可以完全的控制你的Widget.


查看示例

widgetsInTemplate 属性


最后,Dijit模板系统允许你使用widgetsInTemplate属性来通过模板创建组合控件。顾名思义,widgetsInTemplate 指明了你的模板中是否包含其他的Widget(默认值为false).

让我们对我们前面的例子稍作修改,来让它始终包含一个dijit.button

//  修改后的Widget定义
dojo.declare("example.SomeWidget","templates/SomeWidget.html"),widgetsInTemplate: true
    //  你的代码
});
 
//   模板定义
<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>



请注意在修改后的模板中,我们在dijit.form.Button的div节点上定义了一个连接点buttonWidget. 此后我们可以直接使用myWidget.buttonWidget来直接引用这个内嵌的button的widget (而不是仅仅引用这个DOM节点). 使用这种方法,你可以使用一些简单的widget来构建组合的widget,例如一个可以查看邮件列表的widget,或者是一个包含一系列按钮的工具条控件。

注意:使用widgetsInTemplate 时可能会有额外的开销,可能会影响你的widget的性能,甚至整个页面的性能。如果你不是非常清楚的了解这个属性的作用,最好还是将它设为false.


结论

在这篇教程中,我们学习了Dijit 强大的模板系统,使用混入 _Templated,以及你如何使用模板来快速构建自定义的Widget . 我们还介绍了如何在模板中使用附着点,如何绑定DOM事件,以及如何构建包含其他widget的组合Widget的方法。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


我有一个网格,可以根据更大的树结构编辑小块数据.为了更容易知道用户保存了什么,我希望当用户第一次看到网格时,网格处于不可编辑状态.当用户准备好后,他们可以单击编辑按钮,这将使网格的某些部分可编辑.然后,有一个保存或取消按钮可以保存更改或还原.在大多数情况下它是有效的.但
我即将开始开发一款教育性的视频游戏.我已经决定以一种我可以轻松打包为Web,Mobiles和可能的Standalone版本的方式来实现这一目标.我不想使用Flash.因此,我确信(无论如何我会听取建议)使用JavaScript和SVG.我正在对这个问题进行大量研究,但我很难把各个部分放在一起.我知道Raphae
我正在使用带有Grails2.3.9的Dojo1.9.DojoNumberTextBox小部件–我在表单中使用–将固定格式(JavaScript基本格式)的实数值(例如:12.56)设置为HTML表单输入字段(但根据浏览器区域设置显示/编辑它们,所以用户总是看到格式正确的数字).另一方面,Grails期望输入字段根据浏览器
1.引言鉴于个人需求的转变,本系列将记录自学arcgisapiforjavaScript的学习历程,本篇将从最开始的arcgisapiforjavaScript部署开始,个人声明:博文不在传道受业解惑,旨在方便日后复习查阅。由于是自学,文章中可能会出现一些纰漏,请留言指出,不必留有情面哦!2.下载ArcGISforDe
我正在阅读使用dojo’sdeclare进行类创建的语法.描述令人困惑:Thedeclarefunctionisdefinedinthedojo/_base/declaremodule.declareacceptsthreearguments:className,superClass,andproperties.ClassNameTheclassNameargumentrepresentsthenameofthec
我的团队由更多的java人员和JavaScript经验丰富组成.我知道这个问题曾多次被问到,但为了弄清楚我的事实,我需要澄清一些事情,因为我在客户端技术方面的经验非常有限.我们决定使用GWT而不是纯JavaScript框架构建我们的解决方案(假设有更多的Java经验).这些是支持我的决定的事实.>
路由dojo/framework/srcouting/README.mdcommitb682b06ace25eea86d190e56dd81042565b35ed1Dojo应用程序的路由路由FeaturesRoute配置路径参数RouterHistoryManagersHashHistoryStateHistoryMemoryHistoryOutletEventRouterContextInjectionOutl
请原谅我的无知,因为我对jquery并不熟悉.是否有dojo.connect()的等价物?我找到了这个解决方案:http:/hink-robot.com/2009/06/hitch-object-oriented-event-handlers-with-jquery/但是没有断开功能!你知道jquery的其他解决方案吗?有jquery.connect但这个插件在我的测试中不起作用.
与java类一样,在dojo里也可以定义constructor 构造函数,在创建一个实例时可以对需要的属性进行初始化。//定义一个类mqsy_yjvar mqsy_yj=declare(null,{     //thedefaultusername    username: "yanjun",          //theconstructor   
我一直在寻找一些最佳实践,并想知道Dojo是否具有框架特定的最佳实践,还是最好只使用通用的Javascript标准?特别是我主要是寻找一些功能和类评论的指导方针?解决方法:对于初学者来说,这是项目的风格指南:DojoStyleGuide
我有’05/17/2010’的价值我想通过使用dojo.date.locale将其作为“2010年5月17日”.我尝试过使用dojo.date.locale.parse,如下所示:x='05/17/2010'varx=dojo.date.locale.parse(x,{datePattern:"MM/dd/yyyy",selector:"date"});alert(x)这并没有给我所需的日期
我正在尝试创建一个包含函数的dojo类,这些函数又调用此类中的其他函数,如下所示:dojo.provide("my.drawing");dojo.declare("my.drawing",null,{constructor:function(/*Object*/args){dojo.safeMixin(this,args);this.container=args[0];
我知道你可以使用jQuery.noConflict为jQuery做这件事.有没有办法与Dojo做类似的事情?解决方法:我相信你可以.有关在页面上运行多个版本的Dojo,请参阅thispage.它很繁琐,但似乎是你正在寻找的东西.一般来说,Dojo和jQuery都非常小心,不会破坏彼此或其他任何人的变量名.
我有一个EnhancedGrid,用户经常使用复杂的过滤器.有没有办法允许用户保存或标记过滤器,以便将来可以轻松地重新应用它?我知道我可以通过编程方式设置过滤器,但我无法预测用户想要的过滤器.谢谢!编辑:自己做了一些进展…使用grid.getFilter()返回过滤器的JSON表示,然后使用json.strin
我有这个代码:dojo.declare("City",null,{constructor:function(cityid,cityinfo){}});dojo.declare("TPolyline",GPolyline,{constructor:function(points,color){},initialize:function(map){});应该是什
我遇到的问题是我的所有javascript错误似乎来自dojo.xd.js或子模块.我正在使用chrome调试器和许多dijit功能,如dijit.declaration和dojo.parser.这有点烦人,因为它很难找到简单的错误或滑倒.我希望我可以添加一个选项,允许我的调试器在我的非dojo代码中显示选项会发生的位置.我是
我正在使用DojoToolkit数字/解析函数来处理格式化和使用ICU模式语法解析字符串.有没有人知道有可能采取任意ICU模式字符串并以某种方式使用Dojo(或其他)库将其分解为它的部分(例如,对于数字模式,它可以被分解为小数位数,数千个分组等…).我希望这样做,而不需要让我的代码密切了
我有两个看似相关的问题,访问在不同的地方定义的javascript函数.我遇到的第一个问题是调用我在firgbug或safari控制台中定义的函数.我定义了一个名为getRed的函数,如下所示:functiongetRed(row,col){//dosomethingstuffandreturntheredvalueasa
我想添加一个在Ajax调用中指定的外部样式表.我已经找到了一种方法来使用jQuery(参见下面的示例),但是我需要使该方法适应dojoJavaScript框架.JQuery示例$('head').append('<linkrel="stylesheet"type="text/css"href="lightbox_stylesheet.css">');谢谢.解决方法:一旦你
我正在尝试使用dojo.connect将onMouseDown事件连接到图像,如:dojo.connect(dojo.byId("workpic"),"onMouseDown",workpicDown);functionworkpicDown(){alert("mousedown");}类似的代码几行后,我将onMouse*事件连接到dojo.body确实完全正常工作.但是当我点击图像时