转载自Dojo官网
Configuring Dojo with dojoConfig
The dojoConfig
object (formerly djConfig
) allows you to set options and default behavior for various aspects of the toolkit. In this tutorial we'll explore what's possible and how you can put dojoConfig to use in your code.
The dojoConfig
object (known as djConfig
prior to Dojo 1.6) is the primary mechanism for configuring Dojo in a web page or application. It is referenced by the module loader, as well as Dojo components with global options. It can further be used as a configuration point for custom applications, if desired.
The old object name of djConfig
is deprecated, but any existing code using it will continue to work up until 2.0. At the time of writing, most documentation still uses djConfig
; the two names are directly equivalent, but we'll adopt and encourage use of the new dojoConfig
name from here on.
Let's run through some quick examples to see how dojoConfig
works in practice. First, a programmatic example of setting dojoConfig
directly:
View Demo<!-- set Dojo configuration, load Dojo --><script> dojoConfig= { has: { "dojo-firebug": true }, parseOnLoad: false, foo: "bar", async: true }; </script> <script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.1/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) { // Explicitly parse the page parser.parse(); // Find the dialog var dialog = registry.byId("dialog"); // Set the content equal to what dojo.config is dialog.set("content", "<pre>" + JSON.stringify(config, null, "\t") + "</pre>"); // Show the dialog dialog.show();}); </script> <!-- and later in the page --> <div id="dialog" data-dojo-type="dijit/Dialog" data-dojo-props="title: 'dojoConfig / dojo/_base/config'"> </div>
Notice that dojoConfig
is defined in a script block before dojo.js is loaded. This is of paramount
importance—if reversed, the configuration properties will be ignored.
In this example, we have set three flags: parseOnLoad: false
, has
(dojo-firebug
sub-property), and async: true
. Additionally, a custom property has been specified: foo: "bar"
. For this demo, a dijit/Dialog
has been placed in the page. Code that runs from within the require
callback converts the value of dojo.config
to JSON and places it into the dialog for review. Among the results are our properties: parseOnLoad
, has
, and foo
. But there are also a few others, which are related to the fact that the demo page uses the cross-domain, Google-CDN-hosted version of Dojo 1.10.
It is important to note the distinction between dojoConfig
and dojo/_base/config
. dojoConfig
is purely for input purposes—this is how we communicate configuration parameters to the loader and modules. During the bootstrap process, dojo/_base/config
is populated from these parameters for later lookup by module code.
Here's the same example written declaratively:
<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>
In this case, we use the same data-dojo-config
attribute on the Dojo script
element that you've seen in other tutorials and examples. This is entirely functionally equivalent to the previous example. In both cases, the config options we provide are ultimately mixed into the dojo/_base/config
object, where they can be retrieved immediately after the bootstrapping process that takes place as dojo.js
loads.
You can confirm this by setting some new values in dojoConfig
, and checking the dojo.config
object in the console. So, dojoConfig
is a generic configuration property-bag for Dojo. Lets see what options there are and how we can use them.
dojoConfig
, by including an object hash of features as the value of the has
property. 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>
You may be familiar by now with the isDebug
config flag from other tutorials or usage of Dojo in versions prior to Dojo 1.7, to explicitly enable debug information. In Dojo 1.7+, this is now also specified with a has() feature at a higher level of granularity. To enable debugging assistance with Firebug Lite for older versions of Internet Explorer, we can set the dojo-firebug feature (isDebug can still be used to load this, but using the feature will load earlier in the loading cycle in async mode). If you have Firebug or another console available and open, it does nothing. But if you don't have a console, it will load Dojo's version of Firebug Lite, and create the console UI at the bottom of the page. This can be handy when debugging in earlier versions of IE or other browsers without nice developer tools.
To enable debugging messages for deprecated and experimental features, we can set dojo-debug-messages to true (this defaults to false, unless you have set isDebug). if this feature is set to false
, these warnings will be suppressed. For example, to enable a developer console (browser provided or use Firebug Lite) and log debugging messages:
<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.
The following additional options are available to further configure this in-page console:
debugContainerId
: specify a particular element to contain the console UI popup
: use a popup window rather than rendering the console into the current windowDojo received a new loader in Dojo 1.7 to accommodate for the toolkit's new AMD module format. This new loader added a few new configuration options that are crucial to defining packages, maps, and more. For details on the loader, see the Advanced AMD Usage tutorial. Important loader configuration parameters include:
baseUrl
: The base URL prepended to a module identifier when converting it to a path or URL.
baseUrl: "/js"
packages
: An array of objects which provide the package name and location:
packages: [{
name: "myapp",
location: "/js/myapp"
}]
map
: Allows you to map paths in module identifiers to different paths:
map: {
dijit16: {
dojo: "dojo16"
}
}
paths
: a map of module id fragments to file paths:
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
: Defines if Dojo core should be loaded asynchronously. Values can be true
, false
or legacyAsync
, which puts the loader permanently in legacy cross-domain mode.
async: true
parseOnLoad
: If true, parses the page with dojo/parser
when the DOM and all initial dependencies (including those in the dojoConfig.deps
array) have loaded.
parseOnLoad: true
It is recommended that parseOnLoad
be left at false (it defaults to false, so you can simply omit this property), and that developers explicitly require dojo/parser
and call parser.parse()
.
deps
: An array of resource paths which should load immediately once Dojo has loaded:
deps: ["dojo/parser"]
callback
: The callback to execute once deps
have been retrieved:
callback: function(parser) {
// Use the resources provided here
}
waitSeconds
: Amount of time to wait before signaling load timeout for a module; defaults to 0 (wait forever):
waitSeconds: 5
cacheBust
: If true, appends the time as a querystring to each module URL to avoid module caching:
cacheBust: true
Now let's create a simple demo that puts the basic parameters to use. One very common scenario is using Dojo Toolkit from CDN with local modules. Let's say we use Google CDN with modules in the/documentation/tutorials/1.10/dojo_config/demo
space:
View 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.1/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>
By using the
packages
configuration, we've made all references todemo/*
point to our local/documentation/tutorials/1.10/dojo_config/demo/
directory, while allowing any references todojo
,dijit
, anddojox
to come from Google CDN. Had thedemo
package not been defined, the request fordemo/AuthoredDialog
would have gone to//ajax.googleapis.com/ajax/libs/dojo/1.10.1/dojo/demo/AuthoredDialog.js
. We also used alias, by associatingready
withdojo/domReady
.
Extensive documentation about the new loader provides even more details.
The new loader also supports the legacy dojo.require()
resource loading and configuration properties likemodulePaths
covered in this same tutorial for Dojo 1.6, thus allowing developers to safely upgrade existing applications easily and without worry.
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 fromdojoConfig
. 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.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>
In the demo, where we define the locale
property of the dojoConfig
object, we look for a locale=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 the dojo/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 the extraLocale
config property, with an array of string locale names.
When using the dojo/parser
, the lang=
setting on an ancestor DOMNode overrides the dojoConfig.locale
setting. This behavior will change in Dojo 2.0. You can also specify the lang
for individual widgets, overriding thedojoConfig.locale
setting for only that widget.
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:
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.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) {
// 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: "<pre>" + JSON.stringify(config, null, "\t") + "</pre>"
});
// 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 via dojo.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.
In this tutorial, we've covered many common ways in which dojo.config
can be populated—via dojoConfig
ordata-dojo-config
—and how its values influence behavior and supply properties to 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.