实战Dojo与RequireJS集成 之二
Dojo 和requireJS 集成之二
作者: feijia (tiimfei@gmail.com)
在成功了配置了dojo和requireJS之后,我们要仔细分析一下这个模板项目的源代码, 看看Ben提供的程序框架究竟是怎么实现的。
首先我们会注意到 index.html
这是整个应用的入口。 在这里首先会看到一段JavaScript
这段脚本主要做了两个动作:
1. 配置reuqireJS 所要加载的包的名称路径 (有点类似于配置Java的classpath,告诉加载器 模块的位置)
2. 核心逻辑是在ready:function() 它指定了requireJS在整个页面DOM装载完成后要执行的逻辑。 这里就是装入app的依赖模块('app/App'和‘app/config' 。 ),并启动app.startup。
在requireJS 被加载后,它会解析我们这里定义的require对象。并在页面DOM装入完毕后执行ready属性所指定的回调函数。
除了这段脚本, index.html 中还有一段HTML定义了一个名为"app" 的div节点。这个节点就是将由App所创建的Widget所用的节点。 如果App成功运行,则这个Div中的html代码将会替换成由Widget定义的内容。如果App装入失败,用户就会看到写在index.html中的这段静态内容。" if you're seeing this - it didn't work"
下面我们就来看一下app/App是什么内容。 从路径上可以判断,这个模块指向我们项目中的app/App.js
===App.js
App.js 中,它先声明了自己的依赖模块,包括了dojo, dijit/_widget dojo/date/locale 等。 要特别注意的是,它还有一些特别的依赖 例如 'i18n!.nls/App' 这是requireJS的插件定义的格式。 表示这个依赖需要由一个名为i18n的requireJS插件去加载,而所加载的资源的路径为./nsl/App.js
requireJS 的plugin其实本身也是一个标准AMD模块。 ! 之前的部分就是这个模块的名字。 因为这里我们使用的是i18n,因此requireJS会试图先去加载一个名为i18n的模块。 默认的,它会在项目根目录去寻找名为i18n.js的文件加载。 如果我们希望把这个插件的位置移动一下到requirejs目录中,可以这样写
requirejs/i18n!.nls/App
类似的,我们看到另一个'text!./templates/App.html'依赖, text也是一个requireJS的标准插件, 这个插件的作用很简单就是把 一个文件作为字符串加载进来。 这里就是用来加载了一个我们接下来会用到的widget 模板:./templates/App.html
使用requireJS text插件的示例:
分析完了该程序的依赖,我们再来看App的逻辑是什么。 它只有一个return 语句, 内容是一个d.declare调用. 参数d就是dojo。我们知道
dojo.declare 是用来创建类的。 这里我们创建了一个基于widget和Templated的子类. 而参数Widget 对应 dijit/_Widget, Templated 对应 dijit/_Templated , 因此该类继承自dijit/_Widget 和dijit/_Templated。 该类还自
定义了一个模板字符串,和一个i18n 包。 buildRendering 是复写dojo._Widget基类的方法。主要就是获取了2个字符串。一个是用当前默认locale 的月份字符串,另一个是用法语的。 然后就执行父类的方法 this.inherited(arguments)
startup也是dijit._Widget 的基类方法,在一个Widget启动时调用。这里也直接调用了父类的方法,并弹出对话框(App is Started)
所以App实际就是声明了一个新的Widget类并指定了Widget的模板。 那么这个模板是怎么样的?
<div>
<h1>${i18n.heading}</h1>
<p>${i18n.welcome}</p>
<ul>
<li>default locale: ${defaultMonths}</li>
<li>locale 'fr-ch': ${frchMonths}</li>
</ul>
</div>
稍微了解一下dijit的模板机制就可以看懂这个非常简单的Widget模板了。 所有${xxx}的内容都会被相应的变量值替换。 我们在前面dojo.declare 中看到, ${defaultMonths} 和 ${frchMonths} 是自定义的两个字符串. 而i18n.heading 和 i18n.welcome 是从 'i18n!./nls/App 得来的值。
到这里我们已经看完了所有的代码。 下面是该程序的架构示意图:
这个例子看起来有些复杂,其实如果你只是想用requireJS 和dojo 可以非常简单。 几行代码就可以了,但是我们要反问自己AMD的优势究竟是什么?那就是更清晰的模块化代码结构和解藕。 因此这个应用程序模板提供了一个很好的例子,你可以在它的基础上进一步去搭建自己的前端应用。
在架构图中你可以看到它清晰的把加载器,程序入口和配置,程序的主要业务逻辑,以及应用所依赖的类库和资源都做了清晰的隔离. 而所有这些模块和资源全部都是使用requireJS来统一管理和加载的。当应用程序的逻辑逐渐变得复杂,使用各种的本地化资源和第三方类库时,这样模块化的优势就会体现出来.