Home  >  Article  >  Web Front-end  >  JavaScript modular development library SeaJS

JavaScript modular development library SeaJS

高洛峰
高洛峰Original
2016-11-26 09:44:211337browse

SeaJS, a JavaScript modular development library
SeaJS is developed by lifesinger, a domestic genius. The current version is 1.1.1, the source code is less than 1500 lines, it is compressed to 4k, and the quality is extremely high.
This article will talk about some basic usage of SeaJS. It will not cover everything, but it will talk about some details that are not mentioned in the official documents based on my personal understanding.

1. Global interface of SeaJS

SeaJS exposes two identifiers to the world: seajs and define.

If you have already used the identifier seajs in your project and don’t want to change it. At this time SeaJS can give up the global seajs. For example,
var boot = seajs.noConflict();
At this time, boot is equivalent to the previous seajs.

If you even use the identifier define in your project, you don’t want to change it. SeaJS is very tolerant, and its define can also be given away. For example,
var boot = seajs.noConflict(true);
only passes one more true than above. At this time, the global define is gone. At this time, boot.define needs to be used to replace the previous define.

Students who have used jQuery should be familiar with the $.noConflict method, and SeaJS’s noConflict is similar to it.

2. SeaJS module writing method

SeaJS uses the global define function to write modules by default (define can be regarded as a syntax keyword). Define defines three formal parameters: id, deps, and factory.

define(id?, deps?, factory);

This define can easily remind you of AMD’s only API: define function. Or it's confusing, leading to confusion about the difference between SeaJS and RequireJS define.

They all have a global define with three formal parameters, and the corresponding formal parameter names are also the same. It would be mistaken for SeaJS to be an implementation of AMD.

In fact, the first two parameters of define in SeaJS and RequireJS are indeed the same.

IDs are all strings and follow Module Identifiers. deps all refer to dependent modules, and their types are arrays. The only difference lies in the third parameter factory. Although the types are also functions, the meanings of factory parameters are different.

There are two situations for factory parameters in RequireJS
a and deps (array) elements, which correspond one to one. That is, there are several deps and there are several actual parameters of factory.
define(['a', 'b'], function(a, b){
// todo
});
 
b, fixed to require, exports, module (modules/wrappings format).
define(function(require, exports, module){
// todo
});
 
This method is a later compromise of RequireJS to Modules/Wrappings, that is, it is compatible with it. SeaJS's define only supports the second way of writing RequireJS: Modules/Wrappings.
Note: SeaJS follows Modules/Wrappings and Modules/1.1.1. There is no mention of the define keyword in these two specifications. Modules/Wrapping requires that modules be defined using module.declare instead of define. However, only the AMD specification has the definition of define. That is to say, although SeaJS is not an implementation of AMD, it uses the identifier define which is extremely easy to misunderstand.


Having said so much, I haven’t started writing a module yet. Let’s start with the simplest
1. Simple module
define({
  addEvent: function(el, type, fn){},
  removeEvent: function(el, type, fn){},
  fireEvent: function(el , type){}
});
 
In this way, an event module is written, which is no different from writing a singleton. This method is more often used to define pure data modules. It is similar to
var E = {
  addEvent: function(el, type, fn){},
  removeEvent: function(el, type, fn){},
  fireEvent: function(el, type){}
};
 
2. Simple packaging module
define(function() {
  // Some internal auxiliary functions
  // ...
  function addEvent() {
   }
  function removeEvent() {
    // ..
}
function fireEvent() {
} // ..
}
return {
addEvent,
removeEvent: removeEvent,
fireEvent: fireEvent
};
});
 
You know, in this anonymous There are many things you can do in functions. Finally just expose the necessary interfaces. It's similar to
var E = function() {
// Some internal helper functions
// ...
function addEvent() {
} }
function removeEvent() // ..
}
       function fireEvent() {
                                                                                                                                                                                                         ;addEvent: addEvent,
removeEvent: removeEvent,
fireEvent: fireEvent
};
}();

3. NodeJS style packaging module

There is no trace of NodeJS style (Modules/1.1.1) in the above two writing methods. Rewrite it as equivalent to "Method 2".
define(function(require, exports) {
// Some internal helper functions
// ...
function addEvent() {
// ..
}
function removeEvent() {
function fireEvent() {
                                                                                                                                                                                ,,       function fireEvent()                                           . ;
 
You can see that the difference from "Method 2" is:
1: The anonymous function has two parameters require and exports.
2: The export interface does not return an object but uses exports.
And aren’t exports exactly the style of NodeJS? Careful students may find that the require parameter is not used in this example, which is what will be discussed below.

4. Modules with dependencies

"Dependencies" in SeaJS need to be obtained using the require function. Although the second parameter deps of SeaJS's define also means "dependence", it is used by the packaging tool (SPM). of. In addition, SeaJS's require is passed into the anonymous function as a parameter, and RequireJS's require is a global variable. www.2cto.com

The above definition is a module without dependencies, and the following are modules with dependencies.
define(function(require, exports) {
var cache = require('cache');

// ...

exports.bind = bind;
exports.unbind = unbind;
exports.trigger = trigger;
});
 
This event module depends on the cache module, and the function has two formal parameters require and exports. Putting aside the outer anonymous functions and define, it is the standard NodeJS format: use the require function to get dependent modules, and use exports to export existing module interfaces.
In fact, modules with dependencies in SeaJS must be written according to "Method 4", that is, they must be wrapper modules, and the first parameter of the anonymous function must be the identifier "require". That is, you can use require as the original syntax keyword, although it is not global.

Let’s take a look at some interesting phenomena of anonymous function parameters require and exports
a. If you write something other than require, what will be the result if you change it to req.
define(function(req, exports) {
var cache = req('cache');

// ...

exports.bind = bind;
exports.unbind = unbind;
exports.trigger = trigger;
});

Firebug network request is as follows

You will see that the dependent "cache" is not loaded, and of course JS will definitely report an error.

b. Only change the formal parameter of the anonymous function to req, and still use require inside the function.
define(function(req, exports) {
var cache = require('cache');

// ...

exports.bind = bind;

exports.unbind = unbind;

exports.trigger = trigger;
});
 
Look at the network requests

This time the "cache" module was actually requested.

Look carefully at the anonymous function code above where require is not declared, and the formal parameter req is not require. So where does the require in
?
1 var cache = require('cache');
come from?

Looking at the SeaJS source code, we can see that its define function will take the toString of the anonymous function and use regular matching to parse out the "cache" (private parseDependencies function).

We also see that although the cache request is completed, an error is still reported because require is undefined during the execution phase. Therefore, when writing dependent modules, the first parameter of the anonymous function must be require and cannot be changed.

Because factory.toString and regular parsing dependencies are used, the parameters of require cannot be expressions, such as
// The parameters of require cannot be expression operations
require("ui-" + "dialog");

Also cannot use the alias of require, such as
// You cannot assign require to another variable
var req = require;
req("ui-dialog");
 
c. Modify exports to expo
define(function(require , expo) {
var cache = require('cache');

// ...

expo.bind = bind;
expo.unbind = unbind;
expo.trigger = trigger;
});

There is no problem running. That is, the second parameter "exports" can be customized. Obviously SeaJS does not approve of changing "exports" to something else, which obviously destroys the NodeJS style (Modules/1.1.1) module specification---they use "exports" to export the module interface. But this cannot be enforced in SeaJS, it can only be an artificial agreement.

5. Modules with mixed writing methods

The above has introduced how to write modules in various situations. In order to be consistent with the NodeJS style: use require to obtain "dependencies" and exports to export "interfaces". SeaJS has restrictions on obtaining dependencies, that is, require must be used. But exporting does not necessarily have to use exports, that is, exports can be changed to something else. You can even use the "return value" directly.
define(function(require) {
var cache = require('cache');
     
  // ...
     
    // Use the return value to export the interface
    return {
          bind: function() {},
          unbind: Function () {},
Fire: function () {}};
});

We know that the module in nodejs can only be an object. That is, always hang methods on exports. If exports are used to export interfaces in SeaJS, the same applies. Modules can only be JS objects. If you use "return value" to export the interface, the module can be any JS type. The following will return a function type module.
define(function(require) {
var cache = require('cache');

function ad() {
      //...
  }
   
                                                                               
 
3. SeaJS loading method

Although it provides various loading methods (synchronous and asynchronous), the easiest is to write script tags directly in the page. After introducing SeaJS, most of the time you get started is the seajs.use method.
seajs.use has two parameters, the first parameter can be a string (module name) or an array (multiple modules). The second parameter is the callback function. Callback after module loading. The parameters of the callback function correspond to the first parameter one-to-one.
seajs.use('dom', function(dom) {
// todo with dom
});
 
The dom module will be used in the callback function as follows. Of course it also provides the shortcut data-main (same as RequireJS).


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn