AMD-异步模块定义
AMD是RequireJS在推广过程中对模块定义的规范化产出,它是一个概念。
RequireJS是对AMD概念的实现,就好比JavaScript语言是对ECMAScript规范的实现。
RequireJS解决了什么问题?
-
js加载会阻塞网页渲染,加载文件越多,网页失去响应的时间就会越长。
-
js文件之间存在依赖关系,因此必须严格保证加载顺序,代码的编写和维护都会变得困难。
require.js的诞生,就是为了解决这两个问题。
用法
1.加载require.js,一个是把它放在网页底部加载,另一个是写成下面这样:
代码块
<script src="js/require.js" defer async="true" ></script>async属性表明这个文件需要异步加载,避免网页失去响应。IE不支持这个属性,只支持defer,所以把defer也写上。
2.假定我们自己的代码文件是main.js,那么,只需要写成下面这样就行了:
代码块
<script src="js/require.js" data-main="js/main"></script>data-main属性的作用是,指定网页程序的主模块。由于require.js默认的文件后缀名是js,所以可以把main.js简写成main。
3.常见的情况是,主模块依赖于其他模块,这时就要使用AMD规范定义的的require()函数。
代码块
// main.jsrequire(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){// some code here});require()函数接受两个参数。第一个参数是一个数组,表示所依赖的模块,上例就是['moduleA', 'moduleB', 'moduleC'],即主模块依赖这三个模块;第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块。
4.require.js加载的模块,采用AMD规范。也就是说,模块必须按照AMD的规定来写。具体来说,就是模块必须采用特定的define()函数来定义。如果一个模块不依赖其他模块,那么可以直接定义在define()函数之中。
⚠️ 注意:只是模块要用define函数定义,main文件用require。
假定现在有一个math.js文件,它定义了一个math模块。那么,math.js就要这样写:
代码块
// math.jsdefine(function (){var add = function (x,y){return x+y;};return {add: add};});如果这个模块还依赖其他模块,那么define()函数的第一个参数,必须是一个数组,指明该模块的依赖性。当require()函数加载上面这个模块的时候,就会先加载myLib.js文件。
代码块
define(['myLib'], function(myLib){function foo(){myLib.doSomething();}return {foo : foo};});
CMD-同步模块定义
CMD---是SeaJS在推广过程中对模块定义的规范化产出,是一个同步模块定义,是SeaJS的一个标准,SeaJS是CMD概念的一个实现,SeaJS是淘宝团队提供的一个模块开发的js框架。
和requireJS相似的,seaJS 也是用JavaScript编写的JS框架,主要功能是可以按不同的先后依赖关系对 JavaScript 等文件的进行加载工作,可简单理解为JS文件的加载器,确保各个JS文件的先后加载顺序,确保避免了以前因某些原因某个文件加载慢而导致其它加载快的文件需要依赖其某些功能而出现某函数或某变量找不到的问题。
用法
1.在 hello.html 页尾,通过 script 引入 sea.js 并配置后,这样加载入口模块:
代码块
seajs.use("../static/hello/src/main")2.main文件和模块文件遵循统一的写法:
代码块
// 所有模块都通过 define 来定义define(function(require, exports, module) {// 通过 require 引入依赖var $ = require('jquery');var Spinning = require('./spinning');// 通过 exports 对外提供接口exports.doSomething = ...// 或者通过 module.exports 提供整个接口module.exports = ...});CMD是依赖就近,在什么地方使用到插件就在什么地方require该插件,即用即返,是这么一个同步的概念。
ES6模块化特性
在es6之前的javascript中是没有模块化概念的。自从有了这个特性,可以预见AMD和CMD将退出历史舞台,毕竟这是需要引入第三方类库实现的。
在ES6中每一个模块即是一个文件,在文件中定义的变量,函数,对象在外部是无法获取的。如果你希望外部可以读取模块当中的内容,就必须使用export来对其进行暴露(输出)。以import的形式将这个变量进行引入。
CommonJS规范
实际上在前端浏览器里面并不支持module.exports,即模块化,前端浏览器一般使用AMD、CMD、ES6等定义模块化开发的。Nodejs端是使用CommonJS规范的,CommonJS规范---是通过module.exports定义的。
node应用由模块组成,采用的commonjs模块规范。每一个文件就是一个模块,内容对其他的模块都不可见。
CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。require方法用于加载模块。