[JavaScript] AMD/CMD/UMD概述

1. cmd 和 amd

在浏览器中,受网络和浏览器渲染的制约,不能采用同步加载,只能采用异步加载。因而 AMD 规范应运而生javascript

2. AMD

AMD(Asynchronous Module Definition),意思就是"异步模块定义"。它采用异步方式加载模块,制定了定义模块的规则,这样模块和模块的依赖能够被异步加载,不影响它后面语句的运行。全部依赖这个模块的语句,都定义在一个回调函数中,等到加载完成以后,这个回调函数才会运行。这和浏览器的异步加载模块的环境恰好适应(浏览器同步加载模块会致使性能、可用性、调试和跨域访问等问题)css

2.1 define 函数定义模块

本规范只定义了一个函数 "define",它是全局变量 define(id?, dependencies?, factory),参数分别是模块名,依赖,工厂方法html

2.2 require(module,callback)加载模块

  • 引入 require.js
<script type=”text/javascript” defer async=”true” src=”./require.js”></script>
<script type=”text/javascript” defer async=”true” src=”js/init.js”></script>
  • init.js
//require.config 主要是用来对要加载文件的目录进行自定义
require.config({
  baseUrl: 'js',
  paths: {
    "jquery": "../lib/jquery",
    "undersocre": "../lib/underscore",
  }
})

require(['jquery', 'underscore'], function ($, _) {
    $(window).resize(function () {

        var color = ["rgba(", Math.floor(Math.random() * 255), ",", Math.floor(Math.random() * 255), ",", Math.floor(Math.random() * 255), ")"];

        $(".background").css({
            position: "fixed",
            top: "0px",
            bottom: "0px",
            left: "0px",
            right: "0px",
            background: color.join("")
        });
    })

});

第一个参数是一个数组,值是依赖的模块。回调事件会在全部依赖模块加载完毕后才会执行java

2.3 预加载,在定义模块的时候就提早加载好全部模块

3. CMD

该规范解决的浏览器环境下如何编写代码实现模块化,该规范定义可模块的一些遵循的特征,来支持能共用的模块jquery

  1. 模块单一文件
  2. 不该引入模块做用域范围内的新的自由变量
  3. 懒加载

3.1 模块定义

define(factory)定义模块git

  1. define 函数接受一个参数做为模块工厂
  2. factory 能够是一个函数或者其余有效值
  3. 若是 factory 是一个函数,回调函数中会指定三个参数 require,exports,module
  4. 若是个 factory 不是一个函数(对象,字符串),这是模块的接口就是当前对象,字符串
define(function(require, exports, module) {
// do something
});
3.2 require
  1. require 函数接收一个模块标识符(模块标识符也叫模块 id)。
  2. require 函数返回外部模块的导出 API(”导出 API“是用来导出内容给外部模块使用的)。
  3. 若是没法返回请求的模块, require 函数将返回 null。
3.3 require.async
  1. require.async 接收一个模块 Id 列表和一个可选的回调函数。
  2. 回调函数接收模块导出做为函数参数,按照与第一个参数中的顺序相同的顺序列出。
  3. 若是不能返回请求的模块,则回调应该相应地收到 null。

3.4 exports 对象

每一个模块中都有个名叫"exports"的自由变量,这是一个模块能够在模块执行时添加模块 API 的对象。github

3.5 module 对象

  1. module.uri:完整解析的模块 URI(模块 URI 的全路径)。
  2. module.dependencies:模块请求的标识符(模块 id)列表。
  3. module.exports:模块的导出 API(”导出 API“是”用来导出什么东西的 API“)。 它与 export 对象相同。

3.6 模块标识符(模块 id)

  1. 模块的标识符(模块 id)必须是字面量字符串。
  2. 模块标识符(模块 id)不能有相似 .js 的文件名扩展。
  3. 模块标识符(模块 id)应该是加前/后缀的字符串,好比:foo-bar。
  4. 模块标识符(模块 id)能够是相对路径,例如: ./foo 和 ../bar.。

懒加载,在 require 时候才会加载模块api

3.7 一个简单的示例(seajs)

这是 seajs 对象上绑定的属性和方法跨域

seajs01

color.js数组

define("color", function(require, exports, module) {
var \$ = require("jquery");

var createColor = function() {
  return ["rgba(", Math.floor(Math.random() * 255), ",", Math.floor(Math.random() * 255), ",", Math.floor(Math.random() * 255), ")"];
};

module.exports = {
  changeBg: function() {
  \$("#bg").css({
    position: "fixed",
    top: "0px",
    bottom: "0px",
    left: "0px",
    right: "0px",
    background: createColor().join("")
  });
}
};
});

使用非函数的工厂包装模块 text.js

define({
text: "我是初始化程序",
text2: "我要开始执行了"
});

init.js

define("init", function(require, exports, module) {
var color = require("../src/color");
var initText = require("../src/text");
var \$ = require("jquery");

module.exports = {
  start: function() {
    console.log(initText.text + "," + initText.text2);
      $(function() {
              $("#change").click(function() {
      color.changeBg();
      });
    });
  }
};
});

sea.js.html

...

<body id="bg">
    <button id="change">点我我变色</button>
</body>
<script src="./lib/sea.js"></script>
<script>
  seajs.config({
    alias: {
      underscore: "underscore.js",
      init: "./src/init.js",
      color: "./src/color.js"
    }
  });

seajs.use(["underscore", "init"], function(u, init) {
  init.start();
});
</script>
...

目录结构
seajs02

3.8 seajs 引入其余插件或库

通常控制台报错 xxx is not a function

一些库不支持模块引入或者只支持 amd 规范的引入方式,不支持 cmd。全部须要对库进行一些改造

//Underscore.js 1.9.1
if (typeof define === "function" && define.amd && define.amd.jQuery) {
  define("underscore", [], function() {
  return \_;
});
}

//更改以下
if (typeof define === "function" && (define.amd || define.cmd)) {
  define("underscore", [], function() {
  return _;
});
}
//或者整个 define 的判断不要了
if (typeof define === "function") {
  define("underscore", [], function() {
  return _;
});
}

UMD

是一种思想,就是一种兼容 commonjs,AMD,CMD 的兼容写法,define.amd / define.cmd / module 等判断当前支持什么方式,都不行就挂载到 window 全局对象上面去

(function (root, factory) {
    if (typeof define === 'function' && (define.amd || define.cmd)) {
        //AMD,CMD
        define(['b'], function(b){
          return (root.returnExportsGlobal = factory(b))
        });
    } else if (typeof module === 'object' && module.exports) {
        //Node, CommonJS之类的
        module.exports = factory(require('b'));
    } else {
        //公开暴露给全局对象
        root.returnExports = factory(root.b);
    }
}(this, function (b) {
  return {};
}));
相关文章
相关标签/搜索