参考文章:http://dojotoolkit.org/documentation/tutorials/1.10/dojo_config/
难度等级:初级 Dojo版本:1.10
介绍
dojoConfig 对象 (Dojo 1.6 版本前叫djConfig ) 是在web 程序中用来配置 Dojo 的。他会被 module loader引用,其中包含一些全局选项。未来可能采用 configuration point 来配置应用。
旧的名字 djConfig 已废弃,但直到 2.0 前你依然可以使用他。截止当前,很多文档依然使用 djConfig;这两个名字直接等价,但我们提倡从现在起,开始使用新的 dojoConfig。
起步
让我们通过一个例子来快速了解 dojoConfig 如何运作。首先我们直接采用编程方式来展示 dojoConfig 如何设置:
-
-
<script>
-
dojoConfig= {
-
has: {
-
"dojo-firebug": true
-
},
-
parseOnLoad: false,
-
foo: "bar",
-
async: true
-
};
-
</script>
-
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.0/dojo/dojo.js"></script>
-
-
<script>
-
// Require the registry, parser, Dialog, and wait for domReady
-
require(["dijit/registry", "dojo/parser", "dojo/json", "dojo/_base/config", "dijit/Dialog", "dojo/domReady!"]
-
, function(registry, parser, JSON, config) {
-
// 显示调用页面解析器
-
parser.parse();
-
// 定位 dialog
-
var dialog = registry.byId("dialog");
-
// 将内容设置为dojo.config 的 JSON 格式
-
dialog.set("content", "
"
+ JSON.stringify(config, null, "\t") + "");
-
// 显示 dialog
-
dialog.show();
-
});
-
</script>
-
-
-
<div id="dialog" data-dojo-type="dijit/Dialog" data-dojo-props="title: 'dojoConfig / dojo/_base/config'"></div>
注意 dojoConfig 的定义要放在载入 dojo.js 之前。这是至关重要的,如果放在 dojo.js 后面,那 dojoConfig 中的配置会被完全忽略。
例子中,我们设置了三个标识: parseOnLoad: false, has (dojo-firebug sub-property), 和 async: true。另外,如果有自定义属性,可以这样指定: foo: "bar"。在这个例子中,现在页面中放置了一个 dijit/Dialog 。 require 中回调函数将 dojo.config 转为 JSON 并放入 dialog 中,然后显示。显示结果中包含了: parseOnLoad, has, 和 foo。但还会有其他一些东西,基本上是跟我们跨域包含了 Google-CDN-hosted version of Dojo 1.10 相关的一些信息。
区分 dojoConfig 跟 dojo/_base/config 的异同非常重要。dojoConfig 纯粹是用于输入参数—这也是我们将初始化参数传给 loader 和 modules的唯一办法。 在 bootstrap 阶段,会根据前面配置的参数创建 dojo/_base/config ,随后的模块就可以查找引用他了。
下面是采用声明式语法配置 dojoConfig 的例子:
-
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.0/dojo/dojo.js"
-
data-dojo-config="has:{'dojo-firebug': true}, parseOnLoad: false, foo: 'bar', async: 1">
-
</script>
本例中,我们在加载 Dojo 的 script 中添加了data-dojo-config 属性(这种用法你可能在很多文档中见过了)。功能上等价于前面那个例子。以上两个例子中,我们配置的 config 最终都会混入 dojo/_base/config 对象,随后在 bootstrapping process 完成,dojo.js 加载时可立即获取这个对象进行初始化。
要验证这一点,你可以在 dojoConfig 中设置一个新属性 ,然后在console 检查 dojo.config 对象。因此, dojoConfig 就是用来配置 Dojo 属性的。 我们来看看都有哪些属性可用。
has() Configuration
Dojo 1.7+ 版本以后添加了一个重要特性,使用 has() 模板做特性检测(feature detection)。我们可以在 dojoConfig 中通过 has() 定义特性(features), 具体方法就是将定义的属性放入一个 hash 对象作为 has 的值。This feature set is now used for determining certain supported capabilities in Dojo. For example, we could disable the amd factory scan (scanning the module for CommonJS require(module) statements to load as deps) with:
-
<script>
-
dojoConfig = {
-
has: {
-
"dojo-amd-factory-scan": false
-
}
-
};
-
</script>
Debug/Firebug Lite Configuration
Dojo 1.7 版本前你可能已经知道 isDebug 这个配置项了,就是声明是否启用调试信息。 Dojo 1.7 版本以后,这个特性设置放到 has() 里面了,便于更高阶的粒度控制。在较老的 IE 上要启用 Firebug Lite 调试工具,我们可以设置 dojo-firebug 特性(isDebug 也可以使用这个特性,but using the feature will load earlier in the loading cycle in async mode)。如果你使用 Firebug 或者某种支持 console 的浏览器,那什么都不会做。如果你的浏览器不支持 console,这就会启用 Dojo 版本的 Firebug Lite ,同时在页面底部创建一个 console UI。在低版本的 IE 或没有调试工具的浏览器上会非常有用,非常方便。
To enable debugging messages for deprecated and experimental features, 我们可以设置 dojo-debug-messages 为 true (缺省值为 false,除非你设置了 isDebug)。如果设置为 false,警告信息会被滤掉。 下面的例子启用 developer console (浏览器提供或者使用 Firebug Lite) ,并且记录调试信息。
-
<script>
-
dojoConfig = {
-
has: {
-
"dojo-firebug": true,
-
"dojo-debug-messages": true
-
}
-
};
-
</script>
To disable a guaranteed console object, we can set dojo-guarantee-console feature to false. This feature defaults to true and will create a dummy console
object if necessary so that anyconsole.*
logging statements in your code safely and quietly execute without throwing exceptions.
以下设置选项将对页内 console 做进一步配置:
-
debugContainerId: 指定一个特定的元素用来容纳 console UI
-
popup: 将 console 渲染到一个弹出窗口,而非当前窗口。
Loader Configuration
自Dojo 1.7,为适应新的 AMD 格式,Dojo 采用一种新的 loader。 新的 loader 添加了几个重要的配置选项,用于定义 packages,maps 等。更多信息参考: Advanced AMD Usage 。这些配置参数如下:
-
baseUrl: base URL,用来指定模块标识符( module identifier)基础地址,最终转化为路径或 URL
-
-
packages: 类型是对象数组,每条记录可包含一个 package name 和 location:
-
-
packages: [{
-
name: "myapp",
-
location: "/js/myapp"
-
}]
-
map: 允许你将模块标(module identifiers)识符映射到其他路径。
-
-
map: {
-
dijit16: {
-
dojo: "dojo16"
-
}
-
}
-
paths: 可以将 module id 映射到不同的文件路径:
-
-
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 core 采用异步加载。值可以为 true, false 或 legacyAsync( 将 loader 永久地置为 legacy cross-domain mode)
-
-
parseOnLoad:如果为true,则在 DOM 及其初始化依赖(包括 dojoConfig.deps 数组中指定的依赖)全部加载完毕后,马上调用 dojo/parser 解析页面。
-
推荐设置 parseOnLoad 为 false(缺省既为 false,你可以简单忽略这个属性),随后开发人员可以手工通过 require dojo/parser 然后调用解析器: parser.parse().
-
deps::参数为一个数组,每个元素为 resource path,用于指定当 Dojo 加载后需要立即加载执行的模块。
-
-
callback:The callback to execute once deps have been retrieved:
-
-
callback: function(parser) {
-
// Use the resources provided here
-
}
-
waitSeconds“ 设定模块载入的超时时间; 缺省值为 0 (永远等待):
-
-
cacheBust::如果为true, 则在每一个模块 URL 后追加一个 time 作为查询串以避免 module 被缓冲:
现在我们编写个示例,展示基本参数设置。一般通用的方式是使用 CDN 网络上的 Dojo Toolkit,而模块则放在本地。我们假定的场景是:使用Google CDN ,模块放在 /documentation/tutorials/1.10/dojo_config/demo
目录下:
-
<!-- Configure Dojo first -->
-
<script>
-
dojoConfig = {
-
has: {
-
"dojo-firebug": true,
-
"dojo-debug-messages": true
-
},
-
// Don't attempt to parse the page for widgets
-
parseOnLoad: false,
-
packages: [
-
// Any references to a "demo" resource should load modules locally, *not* from CDN
-
{
-
name: "demo",
-
location: "/documentation/tutorials/1.10/dojo_config/demo"
-
}
-
],
-
// Timeout after 10 seconds
-
waitSeconds: 10,
-
map: {
-
// Instead of having to type "dojo/domReady!", we just want "ready!" instead
-
"*": {
-
ready: "dojo/domReady"
-
}
-
},
-
// Get "fresh" resources
-
cacheBust: true
-
};
-
</script>
-
-
<!-- Load Dojo, Dijit, and DojoX resources from Google CDN -->
-
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.0/dojo/dojo.js"></script>
-
-
<!-- Load a "demo" module -->
-
-
<script>
-
require(["demo/AuthoredDialog", "dojo/parser", "ready!"], function(AuthoredDialog, parser) {
-
// Parse the page
-
parser.parse();
-
-
// Do something with demo/AuthoredDialog...
-
});
-
</script>
通过配置 packages
, 我们将所有的 demo/*
引用指向本地目录 /documentation/tutorials/1.10/dojo_config/demo/
, 同时 dojo
, dijit
, 和 dojox
引用继续指向 Google CDN。 如果在 demo
下没有定义某个 package ,比如访问 demo/AuthoredDialog但未定义则将跳转到
//ajax.googleapis.com/ajax/libs/dojo/1.10.0/dojo/demo/AuthoredDialog.js。我们还定义了别名,用 ready 指代
dojo/domReady
。
工作细节,参考:documentation about the new loader 。
The new loader also supports the legacy dojo.require() resource loading and configuration properties like modulePaths covered in this same tutorial for Dojo 1.6, thus allowing developers to safely upgrade existing applications easily and without worry.
Locale and Internationalization
Dojo's i18n system is documented in its own right, and worthy of its own tutorial, but we'll touch on it here just to show dojoConfig at work again.
You can configure the locale to use for any widgets or localized content using Dojo's i18n infrastructure from dojoConfig. The locale option lets you override the default provided to Dojo by your browser. A simple demo shows it at work:
-
<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.0/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", "
"
+ JSON.stringify(config, null, "\t") + "");
-
dialog.show();
-
});
-
</script>
In the demo, where we define the locale property of the dojoConfig object, we look for alocale=xx parameter from the query string. That's a demo artifact; typically you might hard-code the locale. Setting the locale ahead of any module loading ensures that the correct localized message bundle dependencies are loaded where necessary. In this case, we use thedojo/date/locale module to format a date object to a localized string for the Dialog title.
For multi-lingual pages, you will need to load bundles for the other locales as well as the one specified by your browser or the dojoConfig.locale property. In this case, use theextraLocale config property, with an array of string locale names.
When using the dojo/parser, the lang= setting on an ancestor DOMNode overrides thedojoConfig.locale setting. This behavior will change in Dojo 2.0. You can also specify the lang for individual widgets, overriding the dojoConfig.locale setting for only that widget.
Custom Properties
Because dojo.config is always known to exist, and is the logical place to provide for page-scoped configuration, several other modules in Dojo use it for their own particular configuration properties. We see this in Dijit, and especially in DojoX, where module flags and behavior can be set:
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
What works for dojox modules also works for your own applications and modules. dojoConfig is an ideal place to provide configuration for behavior and page- or application-wide properties. Consider the following:
-
<script>
-
dojoConfig = {
-
has: {
-
"dojo-firebug": true
-
},
-
app: {
-
userName: "Anonymous"
-
}
-
};
-
</script>
-
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.0/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) {
-
-
// pull configuration from the query string
-
// and mix it into our app config
-
var queryParams = ioQuery.queryToObject(location.search.substring(1));
-
lang.mixin(config.app, queryParams);
-
-
// Create a dialog
-
var dialog = new Dialog({
-
title: "Welcome back " + config.app.userName,
-
content: "
"
+ JSON.stringify(config, null, "\t") + ""
-
});
-
-
// Draw on the app config to put up a personalized message
-
dialog.show();
-
-
});
-
</script>
In this example, we've tacked on an "app" dojoConfig property, which we later reference viadojo.config to put up a personalized greeting in the Dialog. There are many ways to approach populating dojoConfig.app. It can be pre-populated with reasonable defaults and mixed-in with specific values later. In production, the dojoConfig script block might get written out on the server-side. Alternatively, you could populate it from a cookie with JSON-formatted configuration values, or—as in our earlier example—you could extract configuration data straight from the query string. In development and test mode, you could use a template that provides dummy values, or load a script or module that populates it.
小节
本教程中,关于如何设置 dojo.config 我们探讨了很多通用的方法—通过 dojoConfig 或 data-dojo-config—以及讨论了各选项如何传递并影响 Dojo modules 行为。
The well-defined position and role dojo.config has in the Dojo bootstrap and lifecycle means that the same concept applies neatly to Dojo modules and even your own modules and applications.
跋