模块定义

在 SeaJS 中,所有 JavaScript 文件都应该用模块的形式来书写,并且一个文件只包含一个模块。

define

使用全局函数 define 来定义模块:

define(id?, dependencies?, factory);

id

当前模块的唯一标识。该参数可选。如果没有指定,默认为模块所在文件的访问路径。如果指定的话, 必须是顶级或绝对标识(不能是相对标识)。~~一般由优化工具生成

dependencies

当前模块所依赖的模块,是一个由模块标识组成的数组。该参数可选。如果没有指定,模块加载器会从 factory.toString() 中解析出该数组。~~~factory.toString()中用正则匹配require(..),提取依赖模块,所以一般不用传入dependencies

** 注意:强烈推荐不要设定 iddependencies 参数。 在开发阶段,模块加载器会自动获取这两个参数。部署上线时,则可以通过优化工具来提取这两个参数。

factory

模块的工厂函数。模块初始化时,会调用且仅调用一次该工厂函数。factory 可以是函数, 也可以是对象、字符串等任意值,这时 module.exports 会直接设置为 factory 值。

factory 函数在调用时,会始终传入三个参数: requireexportsmodule, 这三个参数在所有模块代码里可用。 ~~~factory参数可以为字符串?

define(function(require, exports, module) {

  // The module code goes here

});

exports

exports 用来向外提供模块的 API.  ~~~注意 module.exports 和 exports指向同一对象, exports不能在模块定义代码中被重写 如 exports = { foo:function(){..}, bar:200 }

define(function(require, exports) {
// snip...
exports.foo = 'bar';
exports.doSomething = function() {};
});

除了给 exports 对象增加成员,还可以使用 return 直接向外提供 API.

define(function(require, exports) {
// snip...
return {
foo: 'bar',
doSomething: function() {};
};
});

如果 return 语句是模块中的唯一代码,可简化为:~~~直接传json到define(json)中

define({
foo: 'bar',
doSomething: function() {};
});

上面这种格式特别适合定义 JSON 数据。

** 注意:下面这种写法是错误的!

define(function(require, exports) {
// snip...
exports = { // 错误! exports 和 module.exports 无关联了,只是对象字面量而已
foo: 'bar',
doSomething: function() {};
};
});

模块加载器不能获取到新赋给 exports 变量的值。 请使用 returnmodule.exports

require

require 函数用来访问其他模块提供的 API. ~~~用require函数加载依赖模块 require(moduleID)

define(function(require) {
var a = require('./a');
a.doSomething();
});

它接受 模块标识 作为唯一参数。

请牢记,为了使静态分析能成功获取到模块依赖信息,在书写模块时,需要遵循一些简单的 规则

require.async

该方法可用来异步加载模块,并在加载完成后执行回调函数。

define(function(require, exports, module) {
// 加载一个模块
require.async('./b', function(b) {
b.doSomething();
}); // 加载多个模块
require.async(['./c', './d'], function(c, d) {
// do something
});
});

require.resolve

使用 require() 的内部机制来解析并返回模块路径。该函数不会加载模块,只返回解析后的路径。

require.load

该方法可用来异步加载脚本,并在加载完成后,执行指定的回调函数。开发插件时, 可以通过覆盖该方法来实现自定义的资源加载。

require.constructor

有时候,我们需要给所有 require 参数对象添加一些公用属性或方法。这时, 使用 require.constructor 来实现会非常方便。

module

module 参数存储模块的元信息。拥有以下成员:

module.id

当前模块的唯一标识。 require(module.id) 必然返回此模块的 exports

define(function(require, exports, module) {
console.log(module.id); // http://path/to/this/file.js
console.log(require(module.id) === exports); // true
});

module.dependencies

module.dependencies 是一个数组,表示当前模块的依赖列表。

该数组只读:模块加载完成后,修改该数组不会有任何效果。

module.exports

exports 对象由模块系统创建,这不能满足开发者的所有需求, 有时候会希望 exports 是某个类的实例。 这时可用 module.exports 来实现:

define(function(require, exports, module) {
console.log(module.exports === exports); // true
module.exports = new SomeClass();
console.log(module.exports === exports); // false
});

注意,对 module.exports 的赋值需要同步执行,它不能放在回调函数里。 下面这样是不行的:

x.js:

define(function(require, exports, module) {
setTimeout(function() {
module.exports = { a: "hello" };
}, 0);
});

y.js:

define(function(require, exports, module) {
var x = require('./x');
console.log(x.a); // undefined
});

module.constructor

有时候,我们需要给所有 module 参数对象添加一些公用属性或方法。在这种情况下, 使用 module.constructor 可以很好地满足需求。

extend.js:

define(function(require, exports, module) {
var Module = module.constructor; Module.prototype.filename = function() {
var id = this.id;
var parts = id.split('/');
return parts[parts.length - 1];
};
});

a.js:

define(function(require, exports, module) {
exports.filename = module.filename();
}); --------------------------------------------------------------------------------
SeaJS提供了模块化的能力,前面我们已经看到了SeaJS定义模块、引用模块的方法,而这里就要用到SeaJS加载并启动模块的两种方式
a、使用data-main
为<script src="assets/scripts/seajs/sea.js" id="seajsnode"></script>添加data-main="application/application"属性即可:
<script src="assets/scripts/seajs/sea.js" id="seajsnode" data-main="application/application"></script>  
//~~~~ seajs.version == 2.0 data-main可用 seajs.version=2.2.x data-main方式加载入口模块不可用; 类似requirejs的 data-main
SeaJS会根据data-main指定的模块来作为整个应用的入口模块。SeaJS找到这个模块之后,就会加载执行这个模块对应的文件。
那么,SeaJS又是怎么找到这个文件呢?也就是说,这个模块对应的加载路径是多少?
“算法”是:SeaJS_URL_base + data-main
如上文,该例子的SeaJS_URL_base是HelloSeaJS/assets/scripts/

那么,加载路径就是HelloSeaJS/assets/scripts/application/application.js(SeaJS会自动加上.js后缀)

b、使用seajs.use
在<script src="assets/scripts/seajs/sea.js" id="seajsnode">后面加上:
<script> seajs.use("application/application"); </script>
其实这两种效果在这个例子中是一样的,data-main通常用在只有一个入口的情况,use可以用在多个入口的情况,具体用法,看这里:https://github.com/seajs/seajs/issues/260

如果你对你的程序有完全的控制权,建议使用data-main的方式,这样整个页面就只有一段script标签!作为一名前端开发人员,我不得不惊叹:干净、完美!

嗯,SeaJS已经替我们想到了这个问题,于是我们就采用SeaJS提供的方式来合并压缩吧(当然你也可以自己用别的方式压缩)。

SeaJS在2.0之前,是采用SPM作为压缩合并工具的,到了2.0,改为Grunt.js,SPM变为包管理工具,类似NPM(不知道NPM?Google一下吧)

自动化不仅是科技带给社会的便利,也是Grunt带给前端的瑞士军刀。使用Grunt,可以很方便的定制各种任务,如压缩、合并等。使用Grunt之前,需要安装node环境和grunt工具,Google一下,十分钟后回来。

……

Grunt最核心的就两个部分,package.json、Gruntfile.js。

转: seajs手册与文档之--模块定义的更多相关文章

  1. 转: seajs手册与文档之 -- 模块标识

    目录 模块标识 相对标识 顶级标识 普通路径 文件后缀的提示 模块标识 模块标识是一个字符串,用来标识模块.在 require. require.async 等加载函数中,第一个参数都是模块标识.de ...

  2. 转: seajs手册与文档之 -- require规则

    require 规则 正确拼写 不要修改 使用直接量 动态依赖的小提示 书写规则 使用 SeaJS 书写模块代码时,需要遵循一些简单规则: 1. 正确拼写 在模块代码中,第一个参数 必须 命名为 re ...

  3. 转: seajs手册与文档之 -- 配置选项

    config alias preload debug map base charset timeout noConflict config 可以使用 config 方法来配置seajs. seajs. ...

  4. 转: seajs手册与文档之 -- 快速参考 ( ~~useful )

    目录 快速参考 seajs.use seajs.config define require require.async exports module.exports 快速参考 该页面列举了 SeaJS ...

  5. Sea.js 手册与文档

    Sea.js 手册与文档 首页 | 索引 目录 何为 CommonJS 何为 CommonJS 模块 为何封装模块 何为 CommonJS? CommonJS 是一个有志于构建 JavaScript ...

  6. Winform开发框架中的内容及文档管理模块功能介绍

    在开发项目的时候,我们有一些场景需要编辑一些HTML文档,作为内容发布系统的一部分,有时候也需要对一些文档如WORD文档进行编辑管理,这样需要我们对这些内容及文档进行合适的管理.本文主要介绍在WInf ...

  7. Seajs教程 配置文档

    seajs.config Obj alias Obj 别名配置,配置之后可在模块中使用require调用require('jQuery'); seajs.config({ alias:{ 'jquer ...

  8. 三言两语聊Python模块–文档测试模块doctest

    doctest是属于测试模块里的一种,对注释文档里的示例进行检测. 给出一个例子: splitter.pydef split(line, types=None, delimiter=None): &q ...

  9. Python(文件、文件夹压缩处理模块,shelve持久化模块,xml处理模块、ConfigParser文档配置模块、hashlib加密模块,subprocess系统交互模块 log模块)

    OS模块 提供对操作系统进行调用的接口 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname")  改变当前脚本工作目 ...

随机推荐

  1. PASCAL的读入优化

    没readkey的情况 type Tstring=record s:array[0..maxn] of char; n:longint; end; procedure scan(var S:Tstri ...

  2. linux下安装python3.3.4

    下载安装包 # wget http://www.python.org/ftp/python/3.3.4/Python-3.3.4.tgz 解压 # tar -xzvf Python-3.3.4.tgz ...

  3. Please ensure that adb is correctly located at '...adb.exe' and can be executed.

    Android Launch! The connection to adb is down, and a severe error has occured. You must restart adb ...

  4. Oracle 生成指定范围内随机日期

    Oracle生成一个指定范围内的随机日期 /* 年1月1日)的整数偏移量来保存(即把日期保存为一个数字); * 因此可通过寻找‘指定日期’与‘关键日期’相对应的整数偏移量,再加一个指定范围内的随机整数 ...

  5. hdoj 1052 Tian Ji -- The Horse Racing【田忌赛马】 【贪心】

    思路:先按从小到大排序, 然后从最快的開始比(如果i, j 是最慢的一端, flag1, flag2是最快的一端 ),田的最快的大于king的 则比較,如果等于然后推断,有三种情况: 一:大于则比較, ...

  6. 联想S720/S720i通刷刷机包 Vibe V1.0

    ROM介绍 基于官方最新S116底包制作,保证足够的稳定性. 增加VIBE元素,看起来更加大气.美观. 首次增加VIBE元素,720i执行起来无压力,720可能会有点卡.自行酌情刷入. 有bug请文明 ...

  7. [置顶] 内存映射失败MapViewOfFile 失败 返回 8

    问题描述1 在使用内存映射方式读写数据时,将文件A的内容拷贝至文件B中,偶尔会出来文件拷贝后的文件,内容为空,或部分为空 问题分析1 怀疑是内存映射方式读写数据的稳定性(可笑的怀疑,内存映射可以Win ...

  8. Linux下并发网络设计之I/O复用

    I/O 流: 首先我们来定义流的概念,一个流可以是文件,socket,pipe等等可以进行I/O操作的内核对象. 不管是文件,还是套接字,还是管道,我们都可以把他们看作流. 之后我们来讨论I/O的操作 ...

  9. 采用translate实现垂直水平居中

    今天分享一个利用css3新特性实现垂直水平居中的方法. 通过对元素进行绝对定位再配合transform中的translate实现. 代码如下: html <div id="conten ...

  10. 基于SIM 卡卡基不同制作工艺的研究

    1 国内外现行的SIM 卡卡基制作工艺 SIM 卡由卡基和芯片两部分组成.卡基上有植入芯片的台阶式芯片槽,SIM 卡的芯片通过多点焊接植入台阶式芯片槽之中与卡基组成SIM 卡,然后经过个性化数据处理, ...