前端模块化小总结—commonJs,AMD,CMD, ES6 的Module
随着前端快速发展,需要使用javascript处理越来越多的事情,不在局限页面的交互,项目的需求越来越多,更多的逻辑需要在前端完成,这时需要一种新的模式 --模块化编程
模块化的理解:模块化是一种处理复杂系统分解为更好的可管理模块的方式。简单来说就是解耦,简化开发,一个模块就是实现特定功能的文件,可以更方便地使用别人的代码,想要什么功能,就加载什么模块。模块开发需要遵循一定的规范
CommonJS规范
CommonJS就是一个JavaScript模块化的规范,是用在服务器端的node的模块规范,前端的webpack也是对CommonJS原生支持的。
特点:1. 模块输出的是一个值的拷贝, 模块是运行时加载,同步加载
2.CommonJS 模块的顶层this
指向当前模块
有两个API :
require : 加载所要依赖的其他模块
module.exports 或者exports :对外暴露的接口
示例:新建两个模块文件A.js 和 B.js
A.js
//写法一
module.exports = {
a:,
b:
}
//写法二
// module.exports.a=1;
// module.exports.b = 2; //写法三
// exports.a=1;
// exports.b = 2 // 三种写法结果是一样,对外暴露的接口的结果是一致的
B.js console.log(require('./B.js'));//{a:1,b:2}
注意
(1). exports 与module.exports 的区别:exports 是对 module.exports 的引用,不能直接给exports 赋值,直接赋值无效,结果是一个空对象,module.exports 可以直接赋值:如示例
// module.exports = 123; //123
// module.exports = function () { //[Function]
// console.log(123)
// }
// exports = 123; //{}
// exports = function(){ //{}
// console.log(123)
// }
(2). 一个文件不能写多个module.exports ,如果写多个,对外暴露的接口是最后一个module.exports
(3). 模块如果没有指定使用module.exports 或者exports 对外暴露接口时,在其他文件就引用该模块,得到的是一个空对象{}
AMD规范
AMD 即 Asynchronous Module Definition,中文名是“异步模块定义”的意思。它是一个在浏览器端模块化开发的规范,AMD 是 RequireJS 在推广过程中对模块定义的规范化产出,所以AMD规范的实现,就是的require.js了
特点 :异步加载,不阻塞页面的加载,能并行加载多个模块,但是不能按需加载,必须提前加载所需依赖
Amd 的规范中定义了两个重要的api
define(id?,[]?,callbakc): //定义声明模块,参数id 模块id标识(可选),参数二是一个数组(可选),依赖其他模块,最后是回调函数 require([module],callback):// 加载模块,参数一,是数组,指定加载的模块,参数二回调函数,模块加载完成后执行
还有一个配置属性API:
require.config({ baseUrl: //基本路径 paths:// 对象,对外加载的模块名称 : 键值关系,键:自定义模块名称,值 :文件名或者文件路径(不要写文件后缀.js),可以是字符串,数组(如果第一个加载失败,会加载第二个) shim://对象,配置非AMD 模式的文件,每个模块要定义(1)exports:值(指在js文件暴露出来的全局变量,如:window.a)(2)deps: 数组,表明该模块的依赖性 })
注意:paths 的设置加载优化与shim 中配置(AMD模式优先非AMD模式)
以下是例子,加载不同情况的(非AMD 模式,AMD 模式)的例子
示例1 :加载AMD模式模块
//首先,引入requiresJS
//requirejs.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--data-main :设置data-main属性,设置加载主文件路径,默认设置该目录为根目录 如:../js/index.js ,默认把 ../js 作为模块文件的根模块 -->
<script src="../js/require.js" data-main="../js/index.js" defer async="async" type="text/javascript"></script>
</head>
</html> //Math.js
// 定义了AMD 模式的模块,并且引入了jquery 模块 (这里的jquery属于AMD模式)
define(['jquery'],function(_){
//define(['moudel1','moudel2'],callback())
//如果一个模块不依赖其他模块,直接使用define()函数写,
//如果一个模块依赖其他模块,define()第一个参数是数组
//回调函数的参数对应第一个参数数组的值,按顺序
console.log(_);//ƒ (a,b){return new m.fn.init(a,b)}
return {
add:function(x,y){
return x+y;
},
}
}) // index.js (主入口)
//配置好加载路径
require.config({
baseUrl:"../js",
paths:{
"index":"index", // 主入口文件 index:
"jquery":"jquery.min",// jquery 库,符合AMD模式(1.7 版本以上符合AMD)
"maths":"Math", //自定义AMD 模式的模块
}
}) //加载maths.js
require(["maths"],function(_math){
console.log( _math); // {add: ƒ }
})
示例2:加载非AMD 模式的模块,依赖非AMD模块 ,第三方插件(如jquery .lazyload 插件)
这里用到了shim属性配置(加载非AMD 模式)
//index.js (主入口)
//配置好加载路径
require.config({
baseUrl:"../js",
paths:{
"index":"index", // 主入口文件 index:
"jquery":"jquery.min",//jquery 库(1.7 版本以上符合AMD)
"jquery.lazyload":[ // 非AMD 模式 依赖jquery 库的第三方插件
"http://apps.bdimg.com/libs/jquery-lazyload/1.9.5/jquery.lazyload.min",
"jquery.lazyload"
]
//这里加载了百度静态资源cdn和本地的资源(如果第一个加载失败,会加载本地)},
shim:{
"jquery.lazyload":{
deps:["jquery"]//配置 jquery 依赖
}
}
})
//加载jquery 和jquery.lazyload
require(["jquery","jquery.lazyload"],function($){
$("img.lazy").lazyload({effect: "fadeIn"});
})
示例3 加载非AMD 模式 (闭包形式)的模块,有依赖(非AMD模式),自定义(与示例2,差不多)
指定了config 配置的 shim 中exports属性,有返回值
//util.js,
//非闭包,暴露了两个全局变量 utils ,obj
var utils = {};
var obj = {};
utils.add = function(v1,v2){
return v1+v2;
};
obj.reduce = function(x,y){
return x-y;
}
//test1.js
//非AMD 模式的 (闭包形式),一般插件写法,使用wondow 对外暴露了objTest 变量
(function(window,$,obj,utils){
console.log($);//ƒ (a,b){return new m.fn.init(a,b)}
console.log(utils);//{add: ƒ}
console.log(obj);//{reduce: ƒ}
window.objTest = {};//window等于对外暴露接口 })(window,jQuery,obj,utils)// 只能写接口$或者 jQuery(不能写AMD 的模块名称jquery,会报错undefined) //index.js (主入口)
//配置好加载路径
require.config({
baseUrl:"../js",
paths:{
"index":"index", // 主入口文件 index:
"jquery":"jquery.min",//jquery 库(1.7 版本以上符合AMD)
},
shim:{
"test1":{// 非AMD 模式的(闭包形式)
deps:["util"],//设置依赖util:实际是,加载 了 "../js/util.js" 依赖该js 中的所有全局变量
exports:"objTest" , //在test1.js 文件中,使用了window.objTest 对外暴露了接口
},
"util":{ // 非AMD 模式 (非闭包)
deps:["jquery"],//设置依赖
}
}
})
//加载 test1.js
require(["test1"],function(_){
console.log(_);//返回的是一个对象 {},因为在配置中设置了exports
console.log("load finshing...")
});
//加载 util.js
require(["util"],function(_){
console.log(_);//返回的是一个undefind,没有配置exports
console.log("load finshing...")
});
分析示例3:在 test1.js 中,闭包函数,一共传了四个值,分别是 window,jQuery,obj,utils ,
window 就不用说了,jQuery 从哪里传来呢?index.js 主文件中的shim 中test1 模块的依赖只有util (等于加载了util.js 文件,依赖了该文件中的所有全局变量,obj 和utils); 回归jQuery 从哪里加载进来,别忘paths 的配置加载优先shim 配置,所以先加载了paths 中的jquery 模块,即使jquery 也是支持AMD ,但是也是暴露了window.jQuery 全局变量,所以后于jquery 模块的加载,无论是AMD 还是非AMD 都可以得到该全局变量jQuery
注意 :非AMD 模块中依赖AMD 模块,是不可以直接在deps属性中设置AMD的模块名作为依赖,这样是直接报错的
CMD规范
CMD规范是阿里的玉伯提出来的,实现js库为sea.js。 它和requirejs非常类似,即一个js文件就是一个模块,但是CMD的加载方式更加优秀,是通过按需加载的方式,而不是必须在模块开始就加载所有的依赖。
玉伯说过能够亲眼看到seajs死掉也是一种幸福(说明了什么,你懂的)
seajs.config({
//设置别名,方便调用
alias: { 'jquery': ' http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js' }
});
define(function(require, exports, module) {
//引用jQuery模块
var $ = require('jquery');
});
// 加载多个模块,在加载完成时,执行回调
seajs.use(['./a', './b'], function(a, b) {
a.doSomething();
b.doSomething();
});
es6 的module规范
ES6 在语言标准的层面上,实现了模块功能,而且非常简单,ES6到来,完全可以取代 CommonJS 和 AMD规范,成为浏览器和服务器通用的模块解决方案。由vue,Angular React这些mvvm 模式的框架发展,让前端的编程变得模块化,组件化。
特点:1. ES6 模块之中,顶层的this
指向undefined
,即不应该在顶层代码使用this
。
2. 自动采用严格模式"use strict"。须遵循严格模式的要求
3. ES6 模块的设计思想是尽量的静态化,编译时加载”或者静态加载,编译时输出接口
4. ES6 模块export
、
命令可以出现在模块的任何位置,但是必须处于模块顶层。如果处于块级作用域内,就会报错import
5.ES6 模块输出的是值的引用
模块功能主要由两个命令构成:export 和
import
。
export:
用于规定模块的对外接口,
import:
用于输入其他模块提供的功能。
1.export 命令
export
命令除了输出变量,还可以输出函数或类(class),不同的数据类型
export.js
//变量
export var m = ; //函数
export function fn(x, y) {
return x * y;
}; //类class
export class class1{} //export输出的变量就是本来的名字,但是可以使用as关键字重命名
function v1() { ... }
function v2() { ... }
export {
v1 as streamV1,
v2 as streamV2,
v2 as streamV3
};
2.import命令
使用export
命令定义了模块的对外接口以后,其他 JS 文件就可以通过import
命令加载这个模块。
main.js
//静态加载,只加载export.js 文件中三个变量,其他不加载
import {m, fn, streamV1} from './export.js'; //import命令要使用as关键字,将输入的变量重命名。
import {fn as fn1} from './export.js'; //整体加载模块
improt * as all from './export.js'
3.export default 命令
本质上,export default
就是输出一个叫做default
的变量或方法
// export-default.js
export default function foo() {
console.log('foo');
} // 或者写成 function foo() {
console.log('foo');
}
//foo函数的函数名foo,在模块外部是无效的。加载的时候,视同匿名函数加载
export default foo;
//import-default.js
import myfoo from './export-default.js';
比较一下默认输出和正常输出
// 第一组
export default function crc32() { // 输出
// ...
} import crc32 from 'crc32'; // 输入 // 第二组
export function crc32() { // 输出
// ...
}; import {crc32} from 'crc32'; // 输入
分析:上面代码的两组写法,
第一组是使用export default
时,对应的import
语句不需要使用大括号;
第二组是不使用export default
时,对应的import
语句需要使用大括号。
以下的写法是有效的
// modules.js
function add(x, y) {
return x * y;
}
export {add as default};
// 等同于
// export default add; // app.js
import { default as foo } from 'modules';
// 等同于
// import foo from 'modules';
浏览器加载规则:
1、浏览器加载 ES6 模块,也使用<script>
标签,但是要加入type="module"
属性。
浏览器对于带有type="module"
的<script>
,都是异步加载,不会造成堵塞浏览器,
<script type="module" src="./foo.js"></script>
2.ES6 模块也允许内嵌在网页中,语法行为与加载外部脚本完全一致。
<script type="module">
import utils from "./utils.js"; // other code
</script>
es6模块推荐参考:http://es6.ruanyifeng.com/#docs/module
完结。。。谢谢
前端模块化小总结—commonJs,AMD,CMD, ES6 的Module的更多相关文章
- 前端模块化方案全解(CommonJS/AMD/CMD/ES6)
模块化的开发方式可以提高代码复用率,方便进行代码的管理.通常一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数.目前流行的js模块化规范有CommonJS.AMD.CMD以及ES6的模块 ...
- (转) 前端模块化:CommonJS,AMD,CMD,ES6
模块化的开发方式可以提高代码复用率,方便进行代码的管理.通常一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数.目前流行的js模块化规范有CommonJS.AMD.CMD以及ES6的模块 ...
- Javascript模块化编程之CommonJS,AMD,CMD,UMD模块加载规范详解
JavaSript模块化 在了解AMD,CMD规范前,还是需要先来简单地了解下什么是模块化,模块化开发? 模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问 题进行系 ...
- 前端模块化——彻底搞懂AMD、CMD、ESM和CommonJS
我们知道,在NodeJS之前,由于没有过于复杂的开发场景,前端是不存在模块化的,后端才有模块化.NodeJS诞生之后,它使用CommonJS的模块化规范.从此,js模块化开始快速发展. 模块化的开发方 ...
- JavaScript模块化CommonJS/AMD/CMD/UMD/ES6Module的区别
目录 JS-模块化进程 原始的开发方式 CommonJS && node.js AMD && Require.js CMD && Sea.js UMD ...
- CommonJS, AMD, CMD是什么及区别--简单易懂有实例
CommonJS, AMD, CMD都是JS模块化的规范. CommonJS是服务器端js模块化的规范,NodeJS是这种规范的实现. AMD(异步模块定义)和CMD(通用模块定义)都是浏览器端js模 ...
- 前端模块化IIFE,commonjs,AMD,UMD,ES6 Module规范超详细讲解
目录 为什么前端需要模块化 什么是模块 是什么IIFE 举个栗子 模块化标准 Commonjs 特征 IIFE中的例子用commonjs实现 AMD和RequireJS 如何定义一个模块 如何在入口文 ...
- JS JavaScript模块化(ES Module/CommonJS/AMD/CMD)
前言 前端开发中,起初只要在script标签中嵌入几十上百行代码就能实现一些基本的交互效果,后来js得到重视,应用也广泛起来了, jQuery,Ajax,Node.Js,MVC,MVVM等的助力也使得 ...
- JavaScript模块化演变 CommonJs,AMD, CMD, UMD(一)
原文链接:https://www.jianshu.com/p/33d53cce8237 原文系列2链接:https://www.jianshu.com/p/ad427d8879cb 前端完全手册: h ...
随机推荐
- CSS居中问题:块级元素和行级元素在水平方向以及垂直方向的居中问题
元素的居中问题是每个初学者碰到的第一个大问题,在此我总结了下各种块级 行级 水平 垂直 的居中方法,并尽量给出代码实例. 首先请先明白块级元素和行级元素的区别 块级元素 块级元素水平居中 1:marg ...
- dctcp-ns2-patch
diff -crbB ns-allinone-2.35/ns-2.35/queue/red.cc ns-2.35/queue/red.cc *** ns-allinone--- :: --- ns-- ...
- Beyond Compare 4的试用期过了怎么办
修改配置文件(C:\Users\gaojs\AppData\Roaming\BCompare\BCompare.ini)中的时间戳. 时间戳在线转换:https://tool.lu/timestamp ...
- 沉淀,再出发——在Hadoop集群之上安装hbase
在Hadoop集群之上安装hbase 一.安装准备 首先我们确保在ubuntu16.04上安装了以下的产品,java1.8及其以上,ssh,hadoop集群,其次,我们需要从hbase的官网上下载并安 ...
- 【深入理解JAVA虚拟机】第二部分.内存自动管理机制.5.调优实战
高性能硬件上的程序部署策略 在高性能硬件上部署程序,目前主要有两种方式: 通过64位JDK来使用大内存. -- 缺点:GC停顿时间长 使用若干个32位虚拟机建立逻辑集群来利用硬件资源. -- 思 ...
- July 18th 2017 Week 29th Tuesday
My heart is stronger now that you are in it. 我的心里有了你,从此变得更强大. You will no longer feel lonely if ther ...
- 笔记,记事软件(RedbookNote, lifeopraph)
许多人重视记日记是因为它是一种以天为基础保存个人或商务信息的良好方式:持续跟踪每天的生活和思想上的点点滴滴,组织和巩固记忆.思考.商业交易.电子邮件.账单.未来计划.联系人列表,甚至是秘密信息.Lin ...
- IOS AFN (第三方请求)
什么是AFN全称是AFNetworking,是对NSURLConnection.NSURLSession的一层封装虽然运行效率没有ASI高,但是使用比ASI简单在iOS开发中,使用比较广泛 AFN的g ...
- PhoneGap Geolocation结合百度地图api获取地理位置api
一.使用百度地图API 1.地址:http://developer.baidu.com/map/ 2.在js DEMO中获取反地址解析的DEMO 3.修改这个DEMO的密钥,去创建应用就能创建密钥,然 ...
- bzoj2000 [Hnoi2010]stone 取石头游戏
Description A 公司正在举办一个智力双人游戏比赛----取石子游戏,游戏的获胜者将会获得 A 公司提供的丰厚奖金,因此吸引了来自全国各地的许多聪明的选手前来参加比赛. 与经典的取石子游戏相 ...