以下内容都是我的学习总结,可能会有不对的地方,还希望看到的伙伴们批评指正,谢谢啦
一、为什么js文件需要模块化
什么是“模块”:“模块”是为完成某一功能所需的一段程序或子程序。模块是系统中“职责单一”且“可替换”的部分。所谓的模块化就是指把系统代码分为一系列职责单一且可替换的模块。模块化开发是指如何开发新的模块和复用已有的模块来实现应用的功能。
在js文件没有模块化之前,我们往一个页面中引入js文时件,采用的是这种写法:
这样的做法缺点很多,尤其在引入文件过多的时候越明显,主要的缺点如下:
1、请求过多
2、依赖模糊
3、维护困难
这些问题给开发带来了很多困难,尤其是当js文件相互引用,相互依赖时,使用原生引用方式时,会产生很多严重的问题,有可能只要修改一个参数的问题而要修改很多个js文件,维护起来非常的麻烦。
为了解决这些问题,我们就需要js模块化了。
js文件模块化引入方式举例(CommonJS):
下面是几种主流的模块化规范:
二、CommonJS规范
暴露模块的方法:
1、module.exports=value(需要向外暴露的数据或函数等)
2、exports.xxx=value(需要向外暴露的数据或函数等)
示例:
//a.js
module.exports = function () {
console.log("hello world")
}
//b.js
exports.fun = function () {
console.log("module2")
}
引入模块的方法:
require(xxx)
示例:
//app.js
let fun1=require('./a')
let fun2=require('./b')
fun1();
fun2();
提问:我们暴露的是什么?引入的又是什么?
Node内部提供一个Module构建函数。所有模块都是Module的实例。
module对象有下面这些属性:
module.id 模块的识别符,通常是带有绝对路径的模块文件名。
module.filename 模块的文件名,带有绝对路径。
module.loaded 返回一个布尔值,表示模块是否已经完成加载。
module.parent 返回一个对象,表示调用该模块的模块。
module.children 返回一个数组,表示该模块要用到的其他模块。
module.exports 表示模块对外输出的值。
所以我们向外暴露的东西就是:
module.exports 表示模块对外输出的值。 module.exports属性表示当前模块对外输出的接口,其他文件引入(require)加载该模块,实际上就是读取module.exports变量。
为了方便,Node为每个模块提供一个exports变量,指向module.exports。这等同在每个模块头部,有一行这样的命令。
引入的是exports暴露出来的数据,对象或者函数,没有暴露的数据等是模块私有的,外部无法访问。
遵循CommonJS规范的模块,在服务器端(node上运行)的加载是同步的,所以相对于其它的规范,效率就要低一点。
这是我测试CommonJS规范时写的项目:
//moundle1.js
module.exports = function () {
console.log("module1")
}
//moundle2.js
exports.fun = function () {
console.log("module2")
}
//app.js
let fun1=require('./moundle1')
let fun2=require('./moundle2')
fun1();
fun2();
在服务器端(在node上)运行结果:
在浏览器上运行,模块需要提前编译打包
原因:浏览器无法识别require函数,要通过编译工具对require函数进行编译,使浏览器能够识别require函数。
想在浏览器上运行就得需要编译工具:Browserify
npm install -g browserify
安装好编译工具之后, 就多了个命令:browserify
将引入了其它模块的模块用browserify编译打包生成新的js文件,例如:
打包编译后生成了boundle.js文件:
在index.html中引入:
<script src="./js/dist/boundle.js" type="text/javascript" charset="utf-8"></script>
在浏览器上运行结果:
成功!!!
三、AMD规范
每个规范都不相同,但是掌握起来也都很容易,这个我就不赘述啦,想了解的小伙伴可以自己去看文档AMD规范文档
这里给出暴露和引入模块的方法,小伙伴可以对比下不同规范的不同之处:
四、CMD规范
用得很少
五、es6规范
这是目前用得最多的模块化规范,要求掌握
暴露模块的方法:
分别暴露:
export function(){xxx}
export function(){bbb}…
统一暴露:
function fun(){…}
function fun1(){…}
…
export fun fun1;
引入模块的方法:
import xxx from ‘./module1’
import {fun,fun1} from ‘./module2’
遵循es6规范编写的模块和CommonJS规范一样,需要用browserify编译才可以在浏览器上运行,原因一样,如果想项目在低级浏览器上运行(不支持es6语法的浏览器),还得用babel对js文件编译,使es6语法转换成es5语法
跟CommonJS比的优点:
js文件的加载时异步的,效率更高。
语法更为简单。