1、CMD(Common Module Definition) 模块定义规范
Sea.js:一个文件就是一个模块
使用 Sea.js,在书写文件时,需要遵守 CMD (Common Module Definition)模块定义规范。一个文件就是一个模块。前面例子中的 util.js 变成
define(function(require, exports) { exports.each = function (arr) { // 实现代码 }; exports.log = function (str) { // 实现代码 }; });
通过 exports
就可以向外提供接口。这样,dialog.js 的代码变成
define(function(require, exports) { var util = require('./util.js'); exports.init = function() { // 实现代码 }; });
关键部分到了!我们通过 require('./util.js')
就可以拿到 util.js 中通过 exports
暴露的接口。这里的require 可以认为是 Sea.js 给 JavaScript 语言增加的一个 语法关键字,通过 require
可以获取其他模块提供的接口。
这其实一点也不神奇。作为前端工程师,对 CSS 代码一定也不陌生。
@import url("base.css"); #id { ... } .class { ... }
Sea.js 增加的 require
语法关键字,就如 CSS 文件中的 @import
一样,给我们的源码赋予了依赖引入功能。
如果你是后端开发工程师,更不会陌生。Java、Python、C# 等等语言,都有 include
、import
等功能。JavaScript 语言本身也有类似功能,但目前还处于草案阶段,需要等到 ES6 标准得到主流浏览器支持后才能使用。
这样,在页面中使用 dialog.js 将变得非常简单。
<script src="sea.js"></script> <script> seajs.use('dialog', function(Dialog) { Dialog.init(/* 传入配置 */); }); </script>
首先要在页面中引入 sea.js 文件,这一般通过页头全局把控,也方便更新维护。想在页面中使用某个组件时,只要通过 seajs.use
方法调用。
好好琢磨以上代码,我相信你已经看到了 Sea.js 带来的两大好处:
-
通过
exports
暴露接口。这意味着不需要命名空间了,更不需要全局变量。这是一种彻底的命名冲突解决方案。 -
通过
require
引入依赖。这可以让依赖内置,开发者只需关心当前模块的依赖,其他事情 Sea.js 都会自动处理好。对模块开发者来说,这是一种很好的 关注度分离,能让程序员更多地享受编码的乐趣。
语法
Sea.js 推崇一个模块一个文件,遵循统一的写法
define(id?, deps?, factory)
因为CMD推崇
- 一个文件一个模块,所以经常就用文件名作为模块id
- CMD推崇依赖就近,所以一般不在define的参数中写依赖,在factory中写
factory是一个函数,有三个参数,function(require, exports, module)
- require 是一个方法,接受 模块标识 作为唯一参数,用来获取其他模块提供的接口:require(id)
- exports 是一个对象,用来向外提供模块接口
- module 是一个对象,上面存储了与当前模块相关联的一些属性和方法
看个例子:
// 定义模块 myModule.js
define(function(require, exports, module) {
var $ = require('jquery.js')
$('div').addClass('active');
});
// 加载模块
seajs.use(['myModule.js'], function(my){
});