1、简介
使用Dojo有两种主要的方式,分别是编程式和声明式。编程式使用JavaScript实例化对象,并且所有的代码都编码在JavaScript中;声明式使用dojo/parser读取DOM,并解析出被特殊属性(后面我们会知道这个属性是data-dojo-type)装饰的节点和扩展控件行为的特定的<scrpt>标签。
这两种方式都有自己的优缺点,你可能同时使用这两种方式。本文主要讲解声明式语法,使用声明式语法,你需要考虑到下面几点:
- 声明式语法非常简单,并且不需要更深的JavaScript只是。JavaScript可以实现的,声明式语法几乎都能实现,但是声明式语法有它的限制。
- 由于声明式语法的本质(类似html标签),他的性能不如编程式好。因为需要使用dojo/parser解析DOM,并查找需要处理的节点。
2、实例化对象
声明式语法最常用的方式是实例化组件。实现方式是:添加特殊的属性(data-dojo-type)到html标签中,并使用dojo/parser读取文档和实例化组件。看个例子:
<button type="button" id="myButton" data-dojo-type="dijit/form/Button"> <span>Click Me!</span> </button>
上面的例子中我们使用data-dojo-type指定了一个MID(模块ID,这里是Dojo Button),它会指示dojo/parser在该节点在DOM中的位置处实例化一个dijit/form/Button对象。
可以注意到我们添加了一个id属性,它在我们需要获取这个组件的引用时有用。Dijit的基本组件在实例化时,会查找存放他们的节点,如果有id属性,就会使用该id值在dijit/registry中注册,以便将来可以通过该id来引用组件。
我们上面只是放置了一个标签,接下来我们还需要激活dojo/parser。在引入AMD之前的版本,你可以使用Dojo配置data-dojo-config中的选项parSEOnLoad:true来激活dojo/parser。这种使用方式在某些特殊情况下可能会导致非预想结果,因此建议在代码中显示的激活dojo/parser。
<script type="text/javascript" src="lib/dojo/dojo.js" data-dojo-config="async: true"></script> <script type="text/javascript"> require(["dojo/parser","dojo/ready","dijit/form/Button"],function(parser,ready){ ready(function(){ parser.parse(); }); }); </script>
3、配置对象
使用dojo/parser实例化对象很强大,但是如果不能配置组件,就没有任何意义。因此需要一个机制能够在实例化时传入配置信息。
在Dojo的早期版本,我们使用往标签中添加属性的方式,即使属性不起作用。HTML5引进了一种该方式:允许自定义以data-开头的属性,并允许文档严格验证。因此我们使用专有的data-dojo-props属性来包含实例化时需要传送构造器的配置。 例如:
<button id="btn1" data-dojo-type="dijit/form/Button" data-dojo-props="label:'click me',onClick:function(){console.log('yes,clicked');}"> </button>
4、实例化非组件对象
dojo/parser一般用来实例化标签(例如Dijit组件)中的可视化元素,它也可以用来实例化非可视对象。dojo/parser解析配置信息作为第一个参数,node节点的引用作为第二个参数。这对基于dojo/_base/declare的非可视元素也是可行的。
有一个问题是,常规的对象不像Dijit组件一样有一个注册(Dijit组件在实例化时会根据承载元素的id值在dijit/registry中注册以便将来能获取到组件的引用),因此为了在实例化之后能够引用到这些对象,需要在全局区域创建一个引用。dojo/parse通过查找data-dojo-id属性来完成这个工作。
<div data-dojo-id="myStore" data-dojo-type="dojo/store/Memory" data-dojo-props="data: [ { name: 'Alabama',id: 'AL' },{ name: 'Alaska',id: 'AK' },{ name: 'Arizona',id: 'AZ' },{ name: 'California',id: 'CA' },{ name: 'Colorado',id: 'CO' },{ name: 'Connecticut',id: 'CT' },{ name: 'New York',id: 'NY' } ]"></div> <select id="mySelect" name="state" value="CA" data-dojo-type="dijit/form/FilteringSelect" data-dojo-props="searchAttr: 'name',store: myStore"></select>Note:非可视化对象的引用时全局的,不会进行垃圾回收。因此在不需要这个对象之后需要移除,以防止内存泄露。
5、组件行为
处理组件的事件,我们最容易想到的是在JavaScript中编写一段代码来处理(例如调用组件的on方法)。实际上,也可以使用声明式方式来处理事件。
为了在标签中实现事件处理,我们需要使用”声明式脚本“来完成。声明是脚本可以让dojo/parser获取一段内联代码,并且在实例化对象时传入进去。我们来看一个例子:
<div id="someDialog" data-dojo-type="dijit/Dialog" data-dojo-props="title: 'Hello World!'"> <p>I am a dialog. That makes me happy.</p> </div> <button type="button" id="myButton" data-dojo-type="dijit/form/Button"> <span>Click Me!</span> <script type="dojo/on" data-dojo-event="click"> var registry = require("dijit/registry"); registry.byId("someDialog").show(); </script> </button>声明式脚本支持的类型有dojo/on,dojo/aspect,dojo/watch,dojo/method,dojo/connect。