模块化开发
将一个复杂的程序按照一定的规则(规范)分成几个块,并组合在一起。
块的内部数据/实现是私有的,只是向外暴露一些接口(方法)与外部其他模块进行通信
模块化开发的历史
一开始我们使用的是几个函数作为一个模块,但是这种方法容易造成全局变量污染,并且模块之间没有联系。
后来提出对象的方法,就函数作为一个对象的方法来实现,这样就解决了函数作为模块的一些缺点,但是这种方法会暴露所有的模块成员,并且外部成员可以修改内部属性。
现在最常用的是立即执行函数的写法,通过利用闭包的私有作用域的建立,并且不会造成全局变量的污染
(function(win){
function aFn(){
}
function bFn(){
}
win.myMethod={aFn,bFn};
})(window)
IIFE模式增强版:引入依赖
这里是现代模块实现的基石
(function(window,&){
let msg=‘module4’;
function foo(){
console.log(‘foo()’,msg);
}
window.module4=foo;
$(‘body’).css(‘background’,‘red’);
})(window,jQuery)
模块化的好处
减少全局变量的污染,更好的分离,按需加载,高复用性,高可维护性。
但是现实是 页面引入过来的script会造成 请求过多 依赖模糊 难以维护
Commentjs
暴露模块 module.exports=value exports.xxx=value
引入模块 require(xxx)
服务器端实现
Nodejs
module1.js
/**
* 使用module.exports = value向外暴露一个对象
*/
"use strict"
module.exports = {
foo() {
console.log('moudle1 foo()')
}
}
module2.js
/**
* 使用module.exports = value向外暴露一个函数
*/
"use strict"
module.exports = function () {
console.log('module2()')
}
module3.js
/**
* 使用exports.xxx = value向外暴露一个对象
*/
"use strict"
exports.foo = function () {
console.log('module3 foo()')
}
exports.bar = function () {
console.log('module3 bar()')
}
app.js
/**
1. 定义暴露模块:
module.exports = value;
exports.xxx = value;
2. 引入模块:
var module = require(模块名或模块路径);
*/
"use strict"
//引用模块
let module1 = require('./modules/module1')
let module2 = require('./modules/module2')
let module3 = require('./modules/module3')
客户端实现
Browserify 也称为Commonjs的浏览器端的打包工具
代码和服务器端一样 我们需要打包处理
browserify js/src/app.js -o js/dist/bundle.js //output
区分Node与Browserify Node.js运行时动态加载模块(同步) Browserify是在转译(编译)时就会加载打包(合并)require的模块
AMD
专门用于浏览器端,模块的加载是异步的
//dataService.js
define(function(){
let name='dataService.js';
function getName(){
return name;
}
//暴露接口
return {getName};
})
//alerter 定义有依赖的参数
define(['dataService','jquery'],function(dataService,$){
let msg='alerter.js';
function showMsg(){
console.log(msg,dataService.getName());
}
$('body').css('background','deeppink');
//暴露模块
return {showMsg};
})
// main.js 入口文件
(function(){
requirejs.config({
baseUrl:'js/',//基本的路径 出发点在根目录下
paths:{
dataService:'./modules/dataService',
alerter:'./modules/alerter', // 不可以添加js 因为默认添加了
jquery:'./libs/jquery-1.10.1', // 因为它支持AMD
angular:'./libs/angular'
}
shim:{
angular:{
exports:'angular'
}
}
});
requirejs(['alerter','angular'],function(alerter,angular){
alerter.showMsg();
console.log(angular);
})
})
CMD
module1.js
//定义没有依赖的模块
define(function(require,exports,module){
let msg='module1';
function foo(){
return msg;
}
// 暴露模块
module.exports={foo};
});
module2.js
//定义没有依赖的模块
define(function(require,exports,module){
let msg='module2';
function bar(){
console.log(msg);
}
// 暴露模块
module.exports=bar;
});
module3.js
define(function(require,exports,module){
let data='module3';
function fun(){
console.log(data);
}
exports.module3={fun};
});
module4.js
define(function(require,exports,module){
let msg='module4';
// 同步引入
let module2=require('./module2');
module2();
// 异步引入
require.async('./module3',function(module3){
module3.module3.fun();
});
function fun2(){
console.log(msg);
}
exports.fun2=fun2;
})
main.js
define(function(require){
let module1=require('./module1');
console.log(module1.foo());
let module4=require('./module4');
module4.fun2();
})
index.html
<script type='text/javascript' src='js/libs/sea.js'><scirpt>
<script type='text/javascript'>
seajs.use('./js/modules/main.js');
</script>
// module1 module2 module4 module3
ES6
依赖模块需要编译打包处理
module1.js
// 暴露模块 分别暴露
export function foo(){
console.log('foo() module1');
}
export function bar(){
console.log('bar() module1');
}
export let arr = [1,2,3,4,5];
module2.js
// 统一暴露
function fun(){
console.log('fun() module2');
}
function fun2(){
console.log('fun2() module2');
}
export {fun,fun2};
module3.js
// 默认暴露 可以暴露0任意数据类型,暴露什么数据接收到的就是什么数据
export default{
mag:"默认暴露",
foo(){
console.log('我是默认暴露的箭头函数');
}
}
main.js
// 引入其他的模块
// 语法 import xxx from '路径';
import {foo,bar} from './module1'; // import 只是开了一下门 你需要选择你需要的方法
import {fun,fun1} from './module2';
import module3 from './module3';
import $ from 'jquery'
foo();
far();
fun();
fun1();
module3.foo();
使用Babel将es6编译为ES5代码(但包含CommJS语法):babel js/scr -d js/lib
使用Browserify编译成js:browserify js/lib/app.js -o js/lib/bundle.js