Non-organized functions
When I first started writing JavaScript functions, this is usually the case:
The code is as follows |
Copy Code |
function Fun1 () { Some code here } function fun2 () { Some other code here } ... |
Functions are written all in the global environment, the project is very small, and usually there is no conflict problem.
But after more code, gradually found that the function name (English vocabulary) a little less than enough. So we introduce the concept of namespaces and start the modular code.
Functions under namespaces
Under the namespace, my code writes this:
The code is as follows |
Copy Code |
var com = com | | {}; COM.ZFANW = COM.ZFANW | | {}; Com.zfanw.module1 = (function () { Some code here return { FUNC1:FUNC1, ... }; }()); Com.zfanw.module2 = (function () { Some other code here return { FUNC1:FUNC1, ... }; }()); ... |
In the principle of object-oriented, the execution function is usually what I'm going to write:
Com.zfanw.module1.func1.apply ({},[' arg1 ', arg2]);
...
Of course, in order to play less characters, I will also import 1 public API interfaces in the closure: Www.111cn.Net
The code is as follows |
Copy Code |
(Function ($, mod1) { Some code here Mod1.func1.apply ({},[' arg1 ', arg2]); } (JQuery, com.zfanw.module1)); ... |
At this point, the likelihood of code conflicts has been very small, but the problem of code dependencies, multiple scripting file management, blocking problems, gradually surfaced-namespaces approach began to catch.
So Require.js2 appeared.
Require.js
First understand the concept of Require.js Module 3:
A module is different from a traditional script file in so it defines a well-scoped object that avoids polluting the Glo Bal namespace. It can explicitly list its dependencies and get a handle in those dependencies without needing to refer to global objects, But instead receive the dependencies as arguments to the function of that defines the module.
To put it simply, there are two points, one, the module scope is self-contained, does not pollute the global space; second, modules indicate dependencies, and dependencies are imported through parameter passing, without the need for global object references-dependencies also do not pollute global space.
Defining modules
Unlike the old long namespace, Require.js uses the global method define to define the module as follows:
The code is as follows |
Copy Code |
Define (ID, dependencies, Factory); // ? Represents an option |
I divide the modules into two types.
Non-dependent modules
If a module is not dependent on other modules, then it is simple to define, such as the module hello in the hello.js file:
The code is as follows |
Copy Code |
Define (function () { Some code here return { Some public API }; }); |
Modules that have dependencies
The dependent modules are slightly more complex, and when define, we need to list the dependencies of the module:
The code is as follows |
Copy Code |
define ([' jquery '], function ($) {//, such as this module, the execution of the code relies on the jquery,require.js to load the jquery module code and execute it, and then pass the dependent module as a $ parameter in the callback function, the callback function Registering execution results as a module Maybe some code here return { Some public API }; }); |
Here, the ' jquery ' in reliance is the path of the module relative to the BaseURL, which is equivalent to the module ID.
Now, go back and look at the code that imports the public API from the closures written above, and compare it to the Define function:
The code is as follows |
Copy Code |
(Function ($, mod1) { Some code here Mod1.func1.apply ({},[' arg1 ', arg2]); } (JQuery, com.zfanw.module1)); |
In this code, I also imported jquery, and in the closure I also accessed jquery through the external parameters of $. It can be said that it "defines dependencies" in a way that is similar to the Define method, and that the define-imported jquery is not a global variable, so it does not pollute the global environment.
About module names
Define function has three parameters, the first ID is the module name, the format of the name is relative to the BaseURL path to remove file format, such as BaseURL for JS directory, a module in Js/libs/hi.js, then if the name is defined as:
The code is as follows |
Copy Code |
Define (' Libs/hi ', [' jquery '], function ($) {...}); |
The advantage of such a defined form is that the module cannot conflict because a file with the same name is not allowed in the same directory. But also so Require.js suggested that we do not set the module name, because the ' Libs/hi ' module name is set, the module must be placed in the Js/libs directory Hi.js file, to move the location, the module name to follow change. As for the later use of R.js optimization generated module name, that is another thing.
Using modules
What should we do with the various modules that define "dependency" and "No dependencies"? Require.js provides a function, Require (equivalent to Requirejs).
The Require function loads dependencies and executes callbacks, unlike define, which does not register the callback result 4 as a module:
The code is as follows |
Copy Code |
Require ([' jquery '], function ($) {//This functions loads jquery dependencies, and then executes the callback code Console.log ($); }); |
Give a simple example. I have a folder with the file structure as follows:
The code is as follows |
Copy Code |
Index.html js/ Main.js Require.js Jquery.js |
Here Jquery.js is already registered as an AMD module, so the HTML file references require.js:
The code is as follows |
Copy Code |
<script src= "Js/require.js" data-main= "Js/main" ></script> |
Require.js will check the Data-main attribute value, here is Js/main, according to the set, it will load the Main.js file in the JS directory.
Main.js file, I do only one thing, using the JQuery method to get the width of the current window:
The code is as follows |
Copy Code |
Require ([' jquery '], function ($) { var w = $ (window). width (); Console.log (w); }); |
Executing code is as simple as that.
Non-AMD specification modules
But things are far less beautiful than we think, AMD is just a community specification, not a standard, and before it comes, there are a variety of popular libraries, not to mention the code we wrote earlier, so we'll definitely run into a bunch of non-AMD spec modules. In order for Require.js to be able to load them and automatically identify and load dependencies, we have two choices, one, give them all wear a function called define; second, using require.js provided by the configuration options shim, curve to save the nation.
For example, I have a project in hand, for some reason, is still using the jquery 1.4.1 version, and jquery is from the 1.7 version to register as the AMD module, I want to use in require.js, you need to do first shim:
code is as follows |
copy code |
Require.config ({ shim: { ' jquery-1.4.1 ': {//<= this is relative to Main.js path Www.111cn.Net exports: ' JQuery '/ /<= This value requires a little attention, and later mentions }, ' libs/jquery-throttle-debounce.min ': {//<= jquery plugin deps: [' jquery-1.4.1 ']//No need exports, because we're just enhancing the jquery feature } }, }); require ([' jquery-1.4.1 ', ' libs/jquery-throttle-debounce.min '], function ($) { Console.log ($.debounce); }); |
Finish writing shim, found jquery-1.4.1, libs/jquery-throttle-debounce.min such a name is a little long. Here we have two options, one is directly open Modify JS file name, or use require.js provided by the configuration item paths to the module ID to specify the corresponding real file path:
The code is as follows |
Copy Code |
Require.config ({ paths: { ' jquery ': ' jquery-1.4.1 ',//<= module jquery points to js/jquery-1.4.1.js file ' debounce ': ' libs/ Jquery-throttle-debounce.min ' }, shim: { ' jquery ': { exports: ' $ ' }, ' debounce ': { deps: [' jquery '] } } }); require ([' jquery ', ' debounce '], function ($) { console.log ($.debounce); }) |
In this way, it is much more convenient to quote.
In addition, you need to pay attention to the exports item in shim, whose concept is closer to imports, that is, to import global variables. If we change the exports value to a non global variable name, we will cause the incoming callback object to become undefined, for example:
code is as follows |
copy code |
Require.config ({ paths: { ' jquery ': ' jquery-1.4.1 ', }, shim: { ' jquery ': { & nbsp; exports: ' hellojquery '//Here I set the exports value to jQuery/ A value other than $ } } }); require ([' jquery '], function ($) { Console.log ($), and/or here, the undefined }) is displayed; |
Other modules in doing shim, such as underscore need to exports into _.
The benefits of Require.js
What good is require.js to say so much?
Parallel loading
We know that the,<script></script> tag blocks the page, and when it loads the a.js, all subsequent files have to wait for it to load and execute before it can begin loading and executing. and Require.js modules can be downloaded in parallel, no dependencies of the module can be executed in parallel, greatly speed up the page access speed.
Be not worried about dependence
As we define the module, we have decided that the dependencies of the module depend on the –c b,b and rely on a. When I want to use the C module function, I just specify C in the Require function's dependencies:
Require ([' C '], function (c) {...});
As for C-dependent modules, C-dependent module dependencies ... Wait, Require.js will help us.
and the traditional script approach, we must explicitly specify all dependent order:
The code is as follows |
Copy Code |
<script src= "Js/a.js" ></script> <script src= "Js/b.js" ></script> <script src= "Js/c.js" ></script> |
In other words, in the traditional script method, we are most likely to rely on memory or check the contents of the module in this way to determine dependence-inefficient, but also cost the brain.
Reduce global conflicts
By define way, we have reduced the global variable massively, so that the probability of code conflict is very small –javascript bounded by the word, the global variable is the devil, think, we can reduce the number of demons, I think is a good thing.
About global variables
One thing to note is that the require.js environment is not just define and require a few global variables. Many libraries expose variables to the global environment, for example, in jquery, after version 1.7, it registers itself as an AMD module, but also exposes JQuery and $ to the global environment. So in the following code, although we didn't pass in a reference to the callback function, jquery/$ also exists:
The code is as follows |
Copy Code |
Require ([' jquery '], function () { Console.log (JQuery); Console.log ($); }); |