Dojo learning-0: Introduction to AMD Modules
Original article: http://dojotoolkit.org/documentation/tutorials/1.10/modules/
Difficulty level: elementary Dojo version: 1.10
If you are migrating from a version of Dojo lower than 1.7, you may find the1.8 versionof this tutorial useful as it provides some guidance on migrating from Dojo's old module system to AMD. this tutorial will focus strictly on AMD.
Overview
Since Dojo 1.7, Dojo uses the asynchronous module definition (AMD) format to define modules. It is much more powerful than traditional methods, including full asynchronous operations, true package portability, better dependency management, and enhanced error debugging. It is a community-driven specification. modules written in AMD format can be used in any AMD-compatible loader or library. This article will elaborate on AMD and explain how to use it.
What is module?
A module is simply a value that can be referenced. If your module needs to expose some data or methods, the data or methods must represent the attributes of an object in this module. In actual development, we generally do not create a module to encapsulate a simple variable, such as var tinyModule = 'simple value'. Of course you need to do the same. The main value of Modules is to modularize your code and split different functions into different logical units. For example, if you want to define a person with a name address and some other methods, you 'd better encapsulate it together. A module corresponds to a file in the file system.
How can I create a module?
In AMD, to create a module, you must register it in loader.
What is loader? Loader is a piece of JavaScript code used to process module definition and loading. After you load dojo. js or require. js, you have a loader. Interaction with loader:RequireAndDefine..
The global method define allows you to register a module in loader. Let's look at a simple example:
- define(5);
Very simple, but it works well-now we have defined a module with a value of 5.
- define({
- library: 'dojo',
- version: 1.10
- });
The above example goes further. When the module is loaded, we get an object that contains two attributes.
- define(function(){
- var privateValue = 0;
- return {
- increment: function(){
- privateValue++;
- },
- decrement: function(){
- privateValue--;
- },
- getValue: function(){
- return privateValue;
- }
- };
- });
In the above example, we pass a function into define. This function is executed, and its return value is saved as a module by loader. This Code uses the closure to create a private variable privateValue, which cannot be directly accessed by external code, but can be accessed by Returning Methods of the object, the returned object will be the value of the module (modules's value ).
How to load a module?
Beginners need to know how to mark modules. To load a module, you must first identify it. Similar to the module/package in other languages, an AMD module consists of its path and file name. Now we save the preceding sample code as the following file:
- app/counter.js
Let's add a loader (Dojo) and index.html (entry point of the application ). The overall file structure is as follows:
- /
- index.html
- /dojo/
- /app/
- counter.js
The index page is as follows:
-
- <body>
- <script src="dojo/dojo.js" data-dojo-config="async: true"></script>
- <script>
- require([
- "app/counter"
- ], function(counter){
- log(counter.getValue());
- counter.increment();
- log(counter.getValue());
- counter.decrement();
- log(counter.getValue());
- });
- </script>
- </body>
-
Let's analyze the following content:
- App/counter. js module definition file. After calling this file, a module will be registered in loader. Note that the module we define here is a reference pointing to an object, rather than a constructor-this also means that no matter how many times the module is loaded, what we get is a reference pointing to the same object. In general, the module returns constructor, but in some cases, it is more appropriate to return a single-piece object.
- In the file system, the rule for locating the module is to search the subdirectory of the directory where index.html is located, and this subdirectory must be the same as the AMD loader directory (dojo/dojo. js), through this rule we do not need to perform any configuration, loader can know that the module id "app/counter" is pointing to app/counter. js file, load it, and register the returned value as a module.
- In the index.html file, we call require to load the "app/counter" module. We can also use the simplest module Loading Method require (["app/counter"]). This method is applicable to scenarios that do not require a module return value (module reference), but only take advantage of its side effects (such as expanding other modules ). If you need a module return value (module reference), you must provide a callback function. After the module is correctly loaded, loader passes the module as a parameter to the callback function and calls it. Like other functions, the parameter name can be any-the parameter name is not necessarily the same as the module name. Of course, as a best practice, it is recommended that the parameter name be the same as the module name.
Module for Loading Modules-Modules Loading Modules
The previous example is very simple and only shows the basic usage of the define function. When our applications are composed of a bunch of well-organized modules, there must be dependencies between modules. The define function can automatically load dependencies. The list of dependent modules must be passed to the define function.
- define([
- "dojo/_base/declare",
- "dojo/dom",
- "app/dateFormatter"
- ], function(declare, dom, dateFormatter){
- return declare(null, {
- showDate: function(id, date){
- dom.byId(id).innerHTML = dateFormatter.format(date);
- }
- });
- });
This example shows more features of AMD applications:
- Multiple dependencies-the dependency LIST parameters include "dojo/dom" and an imaginary "app/dateFormatter" module.
- Returns a constructor. Here we give the module a proper name, such as "app/DateManager ". When other code uses this module, the Code is as follows:
- require([
- "app/DateManager"
- ], function(DateManager){
- var dm = new DateManager();
- dm.showDate('dateElementId', new Date());
- });
To develop a Dojo application, AMD is the first theme you need to be familiar with, and declare is the second crucial function. If you are not familiar with dojo/_ base/declare, click here to learn: tutorial!
Use plugins
In addition to the conventional modules, AMD loader also divides a class of modules based on functional features, called plugin. Plugins is used to expand the loader feature, rather than simply loading AMD modules. Plugins are similar to common modules to some extent, but behind the module identifier is "! ", Used to identify this as a plugin. "! "The subsequent data will be directly transferred to plugin for processing. Some examples may be helpful for understanding. Dojo provides several default plugins. Four of the most important ones are dojo/text, dojo/i18n, dojo/has, and dojo/domReady. Let's explain it one by one.
Dojo/text
Dojo/text is used to load strings (such as HTML templates) from files ). The load value is buffered. Next time, if a request for the same file exists, no network request is initiated. Builder performs inline processing on strings loaded using dojo/text. For example, to load a template for a templated widget, you can define the module as follows:
- // in "my/widget/NavBar.js"
- define([
- "dojo/_base/declare",
- "dijit/_WidgetBase",
- "dijit/_TemplatedMixin",
- "dojo/text!./templates/NavBar.html"
- ], function(declare, _WidgetBase, _TemplatedMixin, template){
- return declare([_WidgetBase, _TemplatedMixin], {
- // template contains the content of the file "my/widget/templates/NavBar.html"
- templateString: template
- });
- });
Dojo/i18n
Dojo/i18n loads the relevant language resource package according to the locale definition of the browser. The usage is as follows:
- // in "my/widget/Dialog.js"
- define([
- "dojo/_base/declare",
- "dijit/Dialog",
- "dojo/i18n!./nls/common"
- ], function(declare, Dialog, i18n){
- return declare(Dialog, {
- title: i18n.dialogTitle
- });
- });
For more information about i18n, see internationalization tutorial. Dojo/has
The Dojo's loader contains an implementation of the has. js Feature Detection API. the dojo/hasplugin can be used to dynamically adjust the dependency module. The usage is roughly as follows:
- // In "my/events. js"
- Define ([
- "Dojo/dom ",
- "Dojo/has! Dom-addeventlistener ?. /Events/w3c:./events/ie"
- ], Function (dom, events ){
- // If the value of "dom-addeventlistener" is true, the event is "my/events/w3c"
- // Otherwise, the event is "my/events/ie"
- Events. addEvent (dom. byId ("foo"), "click", function (){
- Console. log ("Foo clicked! ");
- });
- });
Dojo/domReady
Dojo/domReady is an alternative to dojo. ready. It will only block the process until the DOM is ready. The usage is as follows:
- // In "my/app. js"
- Define (["dojo/dom", "dojo/domReady! "], Function (dom ){
- // This function will not be executed until the DOM is ready.
- Dom. byId ("someElement ");
- });
Note that in the callback function, we do not define any corresponding parameters for dojo/domReady. This is because the return value is useless to us-we just use it to delay the execution of the callback function. For modules or plugins that do not require the returned values, place them at the end of the list of dependent modules, because the parameters in the callback function correspond to the module names in one order.
Even if you do not need to pass parameters to plugin, the exclamation point is still required. Without it, dojo/domReady will only be loaded as a dependency module, and it will not be enabled as a special function of plugin.
Summary
The basic AMD knowledge described in this tutorial will help you get started, but there will be more knowledge points later. Read the Advanced AMD Usage tutorial to learn the following:
- If loader and packages are stored in different locations or even on different servers, how to configure loader
- Creating packages of portable modules
- Loading multiple versions of the same module or library
- Load non-AMD code
Other resources