Of this series Part I and Part II , introduced the Javascript module prototype and theoretical concepts, and today we will introduce how to use them in practice.
I use a very popular library require.js 。
1、 Why use require.js?
In the earliest days, all the Javascript code was written in a file. It was enough to load this file. Later, there were more and more codes. One file was not enough, so it had to be divided into multiple files and loaded in turn. I believe many people have seen the following web code.
<script src="1.js"></script>
<script src="2.js"></script>
<script src="3.js"></script>
<script src="4.js"></script>
<script src="5.js"></script>
<script src="6.js"></script>
This code loads multiple js files in turn.
This writing has great shortcomings. First, when loading, the browser will stop rendering the web page. The more files loaded, the longer the web page will lose response; Secondly, because there are dependencies between js files, the loading order must be strictly guaranteed (for example, 1. js in the above example must be in front of 2. js). The module with the greatest dependency must be loaded last. When the dependencies are very complex, code writing and maintenance will become difficult.
Require.js was born to solve these two problems:
(1) Realize the asynchronous loading of the js file to avoid losing the response of the web page;
(2) Manage dependencies between modules to facilitate code writing and maintenance.
2、 Loading of require.js
The first step to use require.js is to go to the official website first download Latest version.
After downloading, suppose you put it under the js subdirectory, and you can load it.
<script src="js/require.js"></script>
Some people may think that loading this file may also cause the web page to lose its response. There are two solutions. One is to load it at the bottom of the page, and the other is to write as follows:
<script src="js/require.js" defer async="true" ></script>
The async attribute indicates that the file needs to be loaded asynchronously to avoid the Web page losing response. IE does not support this attribute and only supports defer, so defer is also written.
After loading require.js, the next step is to load our own code. Suppose our own code file is main.js, which is also placed under the js directory. Then, just write as follows:
<script src="js/require.js" data-main="js/main" ></script>
The data main attribute is used to specify the main module of the webpage program. In the above example, it is main.js under the js directory. This file will be the first to be loaded by require.js. Since the default file suffix of require.js is js, you can abbreviate main.js to main.
3、 Writing of main module
The main.js in the previous section is called the "main module", which means the entry code of the entire web page. It is a bit like the main () function of C language, and all the code runs from here.
Let's see how to write main.js.
If our code does not depend on any other module, we can write javascript code directly.
// main.js
Alert ("Loading succeeded!");
However, in this case, it is unnecessary to use require.js. It is really common that the main module depends on other modules, so the require() function defined in the AMD specification should be used.
// main.js
require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
// some code here
});
The require() function takes two arguments. The first parameter is an array, which represents the module it depends on. The example above is ['moduleA ',' moduleB ',' moduleC '], that is, the main module depends on these three modules; The second parameter is a callback function, which will be called when the previously specified modules are successfully loaded. The loaded modules will be passed into the function in the form of parameters, so that these modules can be used inside the callback function.
Require() loads moduleA, moduleB and moduleC asynchronously, and the browser will not lose response; The callback function specified by it will run only after the previous modules are loaded successfully, which solves the dependency problem.
Next, let's look at a practical example.
Assuming that the main module depends on three modules: jquery, underscore, and backbone, main.js can write as follows:
require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone){
// some code here
});
Require.js will first load jQuery, underscore and backbone, and then run the callback function. The code of the main module is written in the callback function.
4、 Module loading
In the last example in the previous section, the dependent modules of the main module are ['jquery ',' underscore ',' backbone ']. By default, require.js assumes that these three modules are in the same directory as main.js, and the file names are jquery.js, underscore.js, and backbone.js, and then they are automatically loaded.
Using the require. config () method, we can customize the loading behavior of the module. Require.config() is written at the head of the main module (main. js). A parameter is an object whose path attribute specifies the loading path of each module.
require.config({
paths: {
"jquery": "jquery.min",
"underscore": "underscore.min",
"backbone": "backbone.min"
}
});
The above code gives the file names of the three modules. By default, the path is in the same directory (js subdirectory) as main.js. If these modules are in other directories, such as the js/lib directory, there are two ways to write them. One is to specify paths one by one.
require.config({
paths: {
"jquery": " lib/ jquery.min",
"underscore": " lib/ underscore.min",
"backbone": " lib/ backbone.min"
}
});
The other is to directly change the base directory (baseUrl).
require.config({
baseUrl: "js/lib",
paths: {
"jquery": "jquery.min",
"underscore": "underscore.min",
"backbone": "backbone.min"
}
});
If a module is on another host, you can also directly specify its URL, such as:
require.config({
paths: {
"jquery": " https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min "
}
});
Require.js requires that each module is a separate js file. In this way, if multiple modules are loaded, multiple HTTP requests will be sent, which will affect the loading speed of the web page. Therefore, require.js provides a Optimization tools After the module is deployed, you can use this tool to combine multiple modules into one file to reduce the number of HTTP requests.
5、 Writing of AMD module
The module loaded by require.js adopts AMD specification. In other words, modules must be written according to AMD regulations.
Specifically, the module must be defined with a specific define() function. If a module does not depend on other modules, it can be directly defined in the define () function.
Suppose you now have a math. js file that defines a math module. Math.js will write as follows:
// math.js
define(function (){
var add = function (x,y){
return x+y;
};
return {
add: add
};
});
The loading method is as follows:
// main.js
require(['math'], function (math){
alert(math.add(1,1));
});
If the module also depends on other modules, the first parameter of the define() function must be an array to indicate the dependency of the module.
define(['myLib'], function(myLib){
function foo(){
myLib.doSomething();
}
return {
foo : foo
};
});
When the require() function loads the above module, the myLib.js file will be loaded first.
6、 Load non-standard modules
Theoretically, the module loaded by require.js must be defined with the define() function according to the AMD specification. However, in fact, although some popular function libraries (such as jQuery) already conform to the AMD specification, more libraries do not. Can require.js load non-standard modules?
The answer is yes.
Before such modules are loaded with require(), they need to use the require.config() method to define some of their characteristics.
For example, both the underscore and backbone libraries are not written in accordance with the AMD specification. If you want to load them, you must first define their characteristics.
require.config({
shim: {
'underscore':{
exports: '_'
},
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
}
});
Require.config() accepts a configuration object. In addition to the path attribute mentioned above, this object also has a shim attribute, which is used to configure incompatible modules. Specifically, each module should define (1) the exports value (the name of the output variable), indicating the name of the external call of the module; (2) Deps array, indicating the dependency of the module.
For example, jQuery plug-ins can be defined as follows:
shim: {
'jquery.scroll': {
deps: ['jquery'],
exports: 'jQuery.fn.scroll'
}
}
7、 Require.js plug-in
Require.js also provides a series of plug-in unit To implement some specific functions.
The domready plug-in allows the callback function to run after the page DOM structure is loaded.
require(['domready!'], function (doc){
// called once the DOM is ready
});
The text and image plug-ins allow require.js to load text and image files.
define([
'text! review.txt',
'image! cat.jpg'
],
function(review,cat){
console.log(review);
document.body.appendChild(cat);
}
);
Similar plug-ins include json and mdown, which are used to load json files and markdown files.
(End)