CMD和AMD探秘
踏上前端这条道路以来,我一直以为自己就是个娴熟的切图工,每天只需要做着重复的劳动,切图,做网站。然而,技术的发展是日新月异的,切图工早就面临淘汰。随着浏览器功能越来越完善,前端项目越来越大,代码越来越复杂,为了适应这种变化,越来越要求前端开发模块化。
首先介绍一下什么是模块化。模块化是指解决某一个复杂问题,按照一种分类的思维把问题进行系统分解,并处理。譬如将巨大的系统代码,整合优化分割成高内聚低耦合的模块,达到便于管理,维护和开发的目的。
模块化设计,必须实现以下能力:
- 定义封装的模块
- 定义新模块对其他模块的以来
- 对其他模块的引入支持。
介绍其中最主要的两种规范,CMD和AMD。
AMD 与 RequireJS
AMD:Asynchronous Module Definition 异步模块定义 [e'sɪŋkrənəs]
AMD采用require([module],callback);加载模块,require有两个参数,一个是依赖的模块数组,一个是回调函数。目前主要有两个Javascript库实现了AMD规范,require.js和curl.js
require.js主要解决以下两个问题:
(1)实现js文件的异步加载,避免网页失去响应;
(2)管理模块之间的依赖性,便于代码的编写和维护。
require.js使用方法
(1)下载js加载入页面
(2)加载自己的代码 <script src="js/require.js" data-main="js/main"></script>
- main.js
- 1 require(['moduleA','moduleB'],function(moduleA,moduleB){
- //code here
- });
- //假定主模块依赖jquery、underscore和backbone这三个模块,main.js就可以这样写:
- require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone){
- // some code here
- });
模块的加载
require.config(); config方法可以对模块的加载行为进行自定义。require.config()就写在主模块(main.js)的头部。参数就是一个对象,这个对象的paths属性指定各个模块的加载路径,baseUrl为基目录
- //main.js
- require.config({
- baseUrl:"js/lib",
- paths:{
- "jquery":"jquery.min",
- "underscore":"underscore".min,
- "backbone":"backbone.min"
- }
- })
AMD模块的写法
模块必须采用特定的define()函数来定义,如果一个模块不依赖于其他模块可以直接定义在define()函数中。
假定一个math模块
- // math.js
- define(function(){
- var add = function(x,y){
- return x+y;
- };
- return {add:add};
- });
- // 加载方法 main.js
- require(['math'],function(math){
- alert(math.add(1,1));
- });
如果这个模块依赖其他模块,define()函数的第一个参数必须是一个数组,指明该模块的依赖性
- define(['myLib'],function(myLib){
- function foo(){
- myLib.func();
- }
- return {foo:foo};
- });
- //当require()函数加载上面这个模块的时候,就会先加载myLib.js文件。
require方法调用模块
- require(['module1','module2'],function(module1,module2){
- module1.func();
- module2.func();
- })
- //在加载 foo 与 bar 两个模块之后执行回调函数实现具体过程。
同时还可以在define定义模块内部进行require调用模块
- define( function( require ){
- var m1 = require( 'module1' ),
- m2 = require( 'module2' );
- ...
- });
加载非规范的模块
在require()加载之前,先用require.config()方法,定义他们的一些特征。
- require.config({
- shim:{
- 'underscore':{
- exports:'_'
- },
- 'backbone':{
- deps:['underscore','jquery'],
- exports:'Backbone'
- }
- }
- });
- /*require.config()接受一个配置对象,这个对象除了有前面说过的paths属性之外,还有一个shim属性,专门用来配置不兼容的模块。具体来说,每个模块要定义
(1)exports值(输出的变量名),表明这个模块外部调用时的名称;
(2)deps数组,表明该模块的依赖性。*/- //比如jQuery插件定义
- shim:{
- 'jquery.scroll':{
- deps:['jquery'],
- exports:'jQuery.fn.scroll'
- }
- }
CMD 与 seaJS (转载)
CMD:Common Module Definition 通用模块加载规范
在CMS中一个模块就是一个文件,格式和AMD有些类似,define(factory);define定义模块,参数factory可以是一个函数或者对象,字符串,当factory为对象字符串时,表示模块的接口是该对象。
定义JSON数据模块:
- define({"foo":"bar"});
通用字符串定义模板模块
- define('this is {{data}}!');
factory 为函数的时候,表示模块的构造方法,执行构造方法便可以得到模块向外提供的接口。
- define( function(require, exports, module) {
- // 模块代码
- });
define( id?, deps?, factory );
define也可以接受两个以上的参数,字符串id为模块标识,数组deps为模块依赖:
- define( 'module', ['module1', 'module2'], function( require, exports, module ){
- // 模块代码
- });
其与 AMD 规范用法不同。
- define(function( require, exports ){
- var a = require('./a');
- a.doSomething();
- });
require.async( id, callback? );
require是同步往下执行的,需要的异步加载模块可以使用 require.async 来进行加载:
- define( function(require, exports, module) {
- require.async('.a', function(a){
- a.doSomething();
- });
- });
exports 是 factory 的第二个参数,用来向外提供模块接口。
- define(function( require, exports ){
- exports.foo = 'bar'; // 向外提供的属性
- exports.do = function(){}; // 向外提供的方法
- });
当然也可以使用 return 直接向外提供接口。
- define(function( require, exports ){
- return{
- foo : 'bar', // 向外提供的属性
- do : function(){} // 向外提供的方法
- }
- });
也可以简化为直接对象字面量的形式:
- define({
- foo : 'bar', // 向外提供的属性
- do : function(){} // 向外提供的方法
- });
与nodeJS中一样需要注意的是,一下方式是错误的:
- define(function( require, exports ){
- exports = {
- foo : 'bar', // 向外提供的属性
- do : function(){} // 向外提供的方法
- }
- });
需要这么做
- define(function( require, exports, module ){
- module.exports = {
- foo : 'bar', // 向外提供的属性
- do : function(){} // 向外提供的方法
- }
- });
传 入的对象引用可以添加属性,一旦赋值一个新的对象,那么值钱传递进来的对象引用就会失效了。开始之初,exports 是作为 module.exports 的一个引用存在,一切行为只有在这个引用上 factory 才得以正常运行,赋值新的对象后就会断开引用,exports就只是一个新的对象引用,对于factory来说毫无意义,就会出错。
seaJS
seajs.use 用来在页面中加载一个或者多个模块
- // 加载一个模块
- seajs.use('./a');
- // 加载模块,加载完成时执行回调
- seajs.use('./a',function(a){
- a.doSomething();
- });
- // 加载多个模块执行回调
- seajs.use(['./a','./b'],function(a , b){
- a.doSomething();
- b.doSomething();
- });
AMD 与 CMD 的区别
下面是玉伯(sea.js创始人)对于 AMD 与 CMD 区别的解释:
- // CMD
- define(function(require, exports, module) {
- var a = require('./a')
- a.doSomething()
- // 此处略去 100 行
- var b = require('./b') // 依赖可以就近书写
- b.doSomething()
- // ...
- })
- // AMD 默认推荐的是
- define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
- a.doSomething()
- // 此处略去 100 行
- b.doSomething()
- // ...
- })
API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。比如 AMD 里,require 分全局 require 和局部
require,都叫 require。CMD 里,没有全局 require,而是根据模块系统的完备性,提供 seajs.use
来实现模块系统的加载启动。CMD 里,每个 API 都简单纯粹。
另外,SeaJS 和 RequireJS 的差异,可以参考:https://github.com/seajs/seajs/issues/277
amdjs 的 require 接口文档 https://github.com/amdjs/amdjs-api/wiki/require
amdjs 的接口文档 https://github.com/amdjs/amdjs-api/wiki
RequireJS和AMD规范 http://javascript.ruanyifeng.com/tool/requirejs.html
知乎 AMD 和 CMD 的区别有哪些? http://www.zhihu.com/question/20351507
JavaScript模块化开发 - AMD规范 http://www.feeldesignstudio.com/2013/09/javascript-module-pattern-amd
模块化设计 http://baike.baidu.com/view/189730.htm
模块化 http://baike.baidu.com/view/182267.htm
CMD和AMD探秘的更多相关文章
- CMD和AMD区别的概括
CMD和AMD区别 AMD CMD 关于依赖的模块 提前执行(不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)), 延迟执行 关于依赖的位置 依赖前置 ...
- CMD和AMD
CMD是国内玉伯在开发SeaJS的时候提出来的,属于CommonJS的一种规范,此外还有AMD,其对于的框架是RequireJS. 二者的异同之处: 二者都是异步(Asynchronuous Modu ...
- CommonJS、CMD和AMD规范分别是什么
CommonJS.CMD和AMD规范分别是什么 Commonjs是用在服务器端的,同步的,如nodejs amd, cmd是用在浏览器端的,异步的,如requirejs和seajs 其中,amd先提出 ...
- CMD和AMD的区别
CMD和AMD俩者之间的区别 AMD和CMD最大的区别是对依赖模块的执行时机处理不同 CMD和AMD都是CommonJS延伸而来的,CommonJS是随着node的出现而出现的,它是一个规范,用于定义 ...
- 转: cmd和amd的区别
AMD 规范在这里:https://github.com/amdjs/amdjs-api/wiki/AMDCMD 规范在这里:https://github.com/seajs/seajs/issues ...
- 两句话概括cmd和amd的区别
=== | === | === | ===AMD | 速度快 | 会浪费资源 | 预先加载所有的依赖,直到使用的时候才执行=== | === | === | ===CMD | 只有真正需要才加载依赖 ...
- 模块化规范:CMD和AMD的区别
https://www.zhihu.com/question/20351507/answer/14859415 AMD(异步模块定义) 是 RequireJS 在推广过程中对模块定义的规范化产出.CM ...
- CMD与AMD区别
- 研究一下javascript的模块规范(CommonJs/AMD/CMD)
最近写react需要使用nodejs作为开发环境,需要通过npm安装一些第三方的依赖库,因此慢慢感觉到nodejs基础薄弱对我带来了一些不安全感,尤其是javascript模块这一块听到了很多概念,比 ...
随机推荐
- ContentProvider官方教程(6)provider支持的数据类型
Provider Data Types Content providers can offer many different data types. The User Dictionary Provi ...
- 使用jquery构建Metro style 返回顶部
个人一直对metro风格的东西情有独钟,偶然间在腾讯网看到一款小插件,蓝色Metro风格的,所以决定把它放到我的博客中,这样做应该不会有版权问题吧orz.. Complete code 后言 我把他原 ...
- js修改浏览器url
var stateObject = {};var title = "";var newUrl = "/";history.pushState(stateObje ...
- Python import 指定目录中的模块
#coding=utf-8 import os,sys sys.path.append('test') # 下级目录(text) parentdir = os.path.dirname(os.path ...
- NPOI大数据分批写入同个Excel
实现过程: 要导出来的数据库数据量很大,一次取出来压力有点大,故分批取出来,导入到同一个Excel. 因为Excel2003版最大行数是65536行,Excel2007开始的版本最大行数是104857 ...
- Codeforces Round #279 (Div. 2) E. Restoring Increasing Sequence 二分
E. Restoring Increasing Sequence time limit per test 1 second memory limit per test 256 megabytes in ...
- VirtualBox全屏切换
用VirtualBox的时候,如果设置为全屏,想再切换回来,没有什么菜单,只有通过键盘的快捷键来操作,才可以恢复. 我常常忘掉,所以老是得去找,以后需要记住这几个按键的快捷键. 1.全屏与非全屏切换: ...
- python中的is、==和cmp()比较字符串
python 中的is.==和cmp(),比较字符串 经常写 shell 脚本知道,字符串判断可以用 =,!= 数字的判断是 -eq,-ne 等,但是 Python 确不是这样子地.所以作为慢慢要转换 ...
- php 怎么设置报错级别 和 控制报错[转]
在Windows环境下:有时在其他环境下运行正常的程序在自己的环境上会报错误 程序会 报出 Undefined index: 这样的错误例如有如下的代码: ...
- 一个CSS中Z-index的用法
一个CSS中Z-index的用法 CSS教程:彻底掌握Z-index属性 大多数的CSS属性都很容易使用.常常,当您对标记语言的元素使用CSS属性时,产生的结果会随着您刷新页面而立即呈现.而另 ...