本篇教程翻译自dojo官网上的dojo1.10教程,中间对部分内容进行了酌情增删,限于个人水平,如果有什么地方翻译不到位或者理解上出了偏差,敬请指出,谢谢!
转载请注明出处。原文地址:ConfiguringDojo with dojoConfig
序言
dojoConfig对象(以前是djConfig)允许你为dojo设置一些默认的选项。在这篇教程里将会为大家说明如何在你的代码里面使用dojoConfig。
介绍
使用dojoConfig对象(1.6版本之前是叫djConfig对象)是在页面中或者应用中主要的配置Dojo的方法。就像Dojo的那些可以全局使用的模块一样,它被模块加载器所引用。如果有这方面的要求的话,在一般的应用中,它可以作为一个配置点。
旧的对象名djConfig已经弃用了,但是在任何使用Dojo2.0之前版本的代码中都支持djConfig,Dojo2.0之后的版本将不再支持。在写这篇教程的时候,大多数的文档依旧在用djConfig对象,这两种写法是等价的。但是建议最好从现在起就开始使用dojoConfig。
开始
让我们来通过一些简单的例子来说明dojoConfig在实践中是如何使用的。一共有两种方式。
下面是第一种配置dojoConfig的示例:
<!-- set Dojo configuration, load Dojo--> <script> dojoConfig= { has: { "dojo-firebug": true }, parseOnLoad: false, foo: "bar", async: true }; </script> <scriptsrc="//ajax.googleapis.com/ajax/libs/dojo/1.10.1/dojo/dojo.js"></script> <script> // Require the registry, parser, Dialog, andwait for domReady require(["dijit/registry", "dojo/parser", "dojo/json", "dojo/_base/config", "dijit/Dialog", "dojo/domReady!"] , function(registry, parser, JSON, config) { purely // Explicitly parse the page parser.parse(); // Find the dialog vardialog = registry.byId("dialog"); // Set the content equal to whatdojo.config is dialog.set("content", "<pre>"+ JSON.stringify(config, null, "\t") + "</pre>"); // Show the dialog dialog.show(); }); </script> <!-- and later in the page --> <divid="dialog"data-dojo-type="dijit/Dialog"data-dojo-props="title: 'dojoConfig /dojo/_base/config'"></div>
需要注意的是定义了dojoConfig的script标签是放在了dojo.js文件之前,这点格外的重要--如果弄反了,配置信息就会被忽略掉。
在这个例子中,我们设置了三项内容:parseOnLoad: false, has (dojo-firebug 的子属性),以及 async: true。此外,还指定了一个惯例属性:foo: "bar".对于这个例子,一个dijit/Dialog组件被放在了页面中,require
的callback函数将dojoConfig的内容转换成了json格式,并放在了dialog中以便展示。在页面结果中能看到当初配置的属性信息: parseOnLoad
, has
, and foo
。但是也包含了一些其他的配置信息,这些额外的配置信息表明了示例页面使用了跨域以及
google CDN
上的
dojo1.10
。
下面是第二种配置dojoConfig的示例:
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.1/dojo/dojo.js" data-dojo-config="has:{'dojo-firebug':true}, parseOnLoad: false, foo: 'bar', async: 1"> </script>在这个例子中,我们在 script 标签中使用了 data-dojo-config 属性,这在功能上和第一种配置方式没有任何区别。在这两个例子中,配置参数将会被加入 dojo/_base/config 对象中。这点你可以通过在 dojoConfig 中加入一些新的值,然后在控制台检查 dojo.config 对象来进行确认。
has() 配置
has()是Dojo1.7+版本加入的一项新的特性。我们可以在通过在dojoConfig中向has属性加入一组对象来为它指明自己的特征。这种设置方式如今已经被用来在Dojo中定义一些确定支持的功能。例如,我们可以使用如下的方式来关闭amd模块扫描:
<script> dojoConfig= { has:{ "dojo-amd-factory-scan":false } }; </script>
Debug/Firebug Lite配置
通过其它系列的教程,或者使用过是Dojo1.7之前的版本,也许你现在对isDebug这个属性已经比较熟悉,它是用来开启debug模式。在1.7+的版本,debug模式也可以通过has()在更高的粒度上进行声明。在旧版本的浏览器上使用Firebug Lite来开启debug,我们需要设置dojo-firebug(使用isDebug也能来加载这些,但是使用has()这种方式可以在异步的模式下更早的加载debug模式)。在开启debug模式之后,如果你有Firebug或者是其他的控制台并且打开了,那么dojo不会在进行任何额外的操作。但是如果你没有这样的一个控制台,它将会加载Dojo的Firebug Lite,并在页面的底部创建一个控制台窗口。这在老版本的IE或者是其它的没有很好的开发者工具的浏览器下很是有帮助。
为那些测试版的或者是已经弃用了的专题显示debug信息,我们可以将dojo-debug-message设置为true(默认的是false,除非你已经设置了isDebug),如果这一项被设置成了false,那么那些警告信息就不会再显示出来。如下例子是开启开发者控制台(浏览器自带的或者是使用Dojo自身的Firebug Lite)并显示debug信息:
<script> dojoConfig= { has:{ "dojo-firebug":true, "dojo-debug-messages":true } }; </script>
如果要禁用控制台,那么可以将 dojo-guarantee-console 选项设置为 false 。这个选项默认为 true ,设置为 true 的时候,如果需要的话它会创建出一个虚拟的控制台以便你的代码里的任何 console.* 的日志信息都安全安静的执行而不会抛出任何的异常。
下面的这些额外的选项能够更大程度的配置这个页面的内的控制台:
- debugContainerId:将控制台放在某个特定的元素内。
- popup:将控制台展现在弹出框中而不是放在页面里。
加载配置
Dojo1.7采用了一种新的加载器来适应新的AMD规范。这个新的加载器新增了很多新的很重要的配置选项,这些配置选项包括了定义packages、maps等等。详情请见在后面系列的教程中会有说明,也可以去官网查看原教程。这些比较重要的配置选项如下:
baseUrl:在根据模块id去寻找相应模块的时候,指定寻找的根路径。
</pre><pre name="code" class="html">baseUrl: "/js"
packages:一个提供了packagename 和这个package对应的路径的对象数组。
packages: [{ name: "myapp", location: "/js/myapp" }]
map:允许你将模块id映射到不同的路径。
<span style="font-family: Arial, Helvetica, sans-serif;"></span>
//PS:意思就是在dijit16这个模块里面,dojo指的就是dojo16这个模块。如果还不明白,在后面马上就会有一个综合的例子 map: { dijit16: { dojo: "dojo16" } }
</pre>paths:模块id跟文件路径的映射map。</p><p><pre name="code" class="html">var dojoConfig = { packages: [ "package1", "package2" ], paths: { package1: "../lib/package1", package2: "/js/package2" } }; // ...is equivalent to: var dojoConfig = { packages: [ { name: "package1", location: "../lib/package1" }, { name: "package2", location: "/js/package2" } ] };
async:定义Dojo是否需要异步加载。Async的值可以是true、false或者是legacyAsync,legacyAsync是将加载器完全的放在传统的跨域模式里。
async: true
parseOnLoad:如果设置为true,那么在DOM和所有要加载的dependencies(包括写在dojoConfig.deps数组中的)加载后,会使用dojo/parse模块来对页面进行解析。
parseOnLoad: true
推荐将
parseOnLoad
设为false(默认值就是false,因此你可以直接忽略这个选项),这样的话开发者就会明确的去require dojo/parser模块并去调用parser.parse()函数。
deps:一个一旦Dojo加载后就会立即开始加载的资源路径的数组。
deps: ["dojo/parser"]
callback:一旦取到deps,就会执行callback函数。
callback: function(parser) { // Use the resources provided here }
waitSeconds:等待多长时间才会将模块标记为加载超时。默认是0(一直等待)。
waitSeconds: 5
cacheBust:如果是true,为每一个模块的URL添加一个时间来作为querystring,以便避免从缓存中读取内容。
cacheBust: true
现在我们来创建一个简单的使用这些基本参数的例子。一个非常常见的情况就是我们将CDN上的DojoToolKit和本地的模块放在一起使用。现在假设我们使用的是GoogleCDN,本地的模块的路径为/documentation/tutorials/1.10/dojo_config/demo,创建的例子如下:
<!-- Configure Dojo first --> <script> dojoConfig = { has: { "dojo-firebug": true, "dojo-debug-messages": true }, // 不用尝试解析页面上的窗体小部件 parseOnLoad: false, packages: [ // 任何指向 "demo" 的引用在加载"demo"这个模块的时候都应该加载本地的, 而不是从 CDN { name: "demo", location: "/documentation/tutorials/1.10/dojo_config/demo" } ], // 超时时间为10s waitSeconds: 10, map: { // 不想使用 "dojo/domReady!", 就是想用 "ready!" 来替代 "*": { ready: "dojo/domReady" } }, // 不会加载缓存中的资源 cacheBust: true }; </script> <!-- 加载<span style="font-family: Arial, Helvetica, sans-serif;">Google CDN上的</span><span style="font-family: Arial, Helvetica, sans-serif;"> Dojo, Dijit, and DojoX资源 --></span> <script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.1/dojo/dojo.js"></script> <!-- 加载 "demo" 模块 --> <script> require(["demo/AuthoredDialog", "dojo/parser", "ready!"], function(AuthoredDialog, parser) { // 解析页面 parser.parse(); // Do something with demo/AuthoredDialog... }); </script>
通过使用packages配置,我们将所有指向demo/*的引用都又指向到了我们本地的/documentation/tutorials/1.10/dojo_config/demo/
这个目录,同时呢又影响CDN上的dojo,dijit,还有dojox的使用。如果没有定义demo这个package,那么对demo/ AuthoredDialog
的请求就会转向 //ajax.googleapis.com/ajax/libs/dojo/1.10.1/dojo/demo/AuthoredDialog.js。我们也使用了别名,就是用ready来指代
dojo/domReady
.。
新的加载器也支持传统的dojo.require()的资源加载,也可以配置比如modulePaths
这样的在1.6版本就已经被覆盖掉了属性,这样的话开发者就可以放心的升级已经有的应用。
本地化和国际化
Dojo的i18n(国际化)系统是按照自己的规则习惯来写的,对他本身的教程也很有用,我们在这里就接触这个仅仅是为了说明dojoConfig可以针对国际化来进行一些配置。 你可以使用dojoConfig的国际化功能来为任何的小部件或者内容来进行本地化配置,本地化选项可以允许你重写浏览器默认给Dojo的内容。下面的简单例子就是展示它是如何工作的:<script> var dojoConfig = { has: { "dojo-firebug": true, "dojo-debug-messages": true }, parseOnLoad: true, // look for a locale=xx query string param, else default to 'en-us' locale: location.search.match(/locale=([\w\-]+)/) ? RegExp.$1 : "en-us" }; </script> <script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.1/dojo/dojo.js"></script> <script> require(["dojo/date/locale", "dijit/Dialog", "dojo/json", "dojo/_base/config", "dojo/_base/window", "dojo/i18n", "dojo/domReady!"] , function(locale, Dialog, JSON, config, win) { var now = new Date(); var dialog = new Dialog({ id: "dialog", // set a title on the dialog of today's date, // using a localized date format title: "Today: " + locale.format(now, { formatLength:"full", selector:"date" }) }).placeAt(win.body()); dialog.startup(); dialog.set("content", "<pre>" + JSON.stringify(config, null, "\t") + "</pre>"); dialog.show(); }); </script>点此查看本示例的演示
在这个示例中,我们为dojoConfig对象定义了locale这个属性,我们从query string中去匹配locale=xx这个参数。这只是一个演示示例,一般情况下locale的值是个写死的固定值。在所有的模块加载前定义locale属性,可以保证任何绑定到了dependencies数组的本地化信息都能够按需正常显示。在这个例子中,我们使用了dojo/date/locale模块来将一个日期对象格式化为了本地的字符串,然后将它设置为了对话框的标题。
对于使用了多语言的页面,就像浏览器或者是dojoConfig.locale属性指定的那个locale值一样,你还需要再加载其他的locale内容。这种情况下,就要使用extraLocale这个配置属性,这个属性对应的值是一个存放了localename的字符串数组。
当使用了dojo/parser模块的时候,DOM节点上的lang=?会覆盖掉dojoConfig.locale。这在Dojo2.0会进行改进。当然你也可以为单个的部件指定lang这个属性,从而只在那个部件上覆盖掉dojoConfig.locale。
自定义属性
鉴于dojo.config是众所周知的配置页面属性的地方,Dojo中的其他模块也会在这里对它们自身进行一些配置。我们经常看到的有对dijit、尤其是dojox的配置。
Dijit Editor
allowXdRichTextSave
dojox GFX
dojoxGfxSvgProxyFrameUrl, forceGfxRenderer, gfxRenderer
dojox.html metrics
fontSizeWatch
dojox.io transports and plugins
xipClientUrl, dojoCallbackUrl
dojox.image
preloadImages
dojox.analytics plugins
sendInterval, inTransitRetry, analyticsUrl, sendMethod, maxRequestSize,idleTime, watchMouseOver, sampleDelay, targetProps, windowConnects, urchin
dojox.cometd
cometdRoot
dojox.form.FileUploader
uploaderPath
dojox.mobile
mblApplyPageStyles, mblHideAddressBar, mblAlwaysHideAddressBar,mobileAnim, mblLoadCompatCssFiles
它可以在dojox的模块中使用,那当然也能够使用在你自己的模块中。dojoConfig是一个非常理想的配置页面或者应用属性的地方。注意下面这个例子:
<script> dojoConfig = { has: { "dojo-firebug": true }, app: { userName: "Anonymous" } }; </script> <script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.1/dojo/dojo.js"></script> <script> require(["dijit/Dialog", "dijit/registry", "dojo/parser", "dojo/_base/lang", "dojo/json", "dojo/_base/config", "dojo/io-query", "dojo/domReady!"] , function(Dialog, registry, parser, lang, JSON, config, ioQuery) { // 从query string中获取配置信息,并且将它加入到我们的app配置 var queryParams = ioQuery.queryToObject(location.search.substring(1)); lang.mixin(config.app, queryParams); // 创建一个对话框 var dialog = new Dialog({ title: "Welcome back " + config.app.userName, content: "<pre>" + JSON.stringify(config, null, "\t") + "</pre>" }); // 使用app config来展示个性化信息 dialog.show(); }); </script>点此查看本示例的演示
在这个示例中,我们在dojoConfig定义了一个app属性,随后我们通过引用dojo.config来为对话框提供了个性化的问候信息。有很多给dojoConfig.app赋值的方式。它可以先赋上一个合理的默认值,然后随后再加入特定的值。在生产模式中,写着dojoconfig的script块可能会写在了服务端。另外你可以通过cookie中以JSON格式保存的配置信息的值来构建它,或者像我们前面的例子——你可以直接从querystring中提取配置数据。在开发和测试模式,你可以使用一个模版提供虚拟的值,或者载入一个脚本或模块来构建它。
总结
在这篇教程中,我们展示了常用的构建dojo.config的方式--通过dojoConfig或者是data-dojo-config--以及配置信息是如何影响模块的行为的。Dojo引导和生命周期中有着清晰位置和角色的dojo.config属性意味着相同的概念也适用于Dojo模块甚至是你自己的模块及应用。
扩展阅读
- dojoConfig (djConfig) documentation
- Dojo AMD loader configuration reference
- i18n docs