1. 什么是模块化?
将一个复杂的程序依据一定的规则封装成几个块(文件),并最终组合在一起。块(文件)的内部数据/实现是私有的,只是向外部暴露一些接口(方法)与外部其他模块通信。
2.模块的进化史
1.最早的代码风格,全局被污染,容易造成命名冲突。
function foo(){
//...
}
function bar(){
//...
}
2.简单封装:namespace模式。虽然减少了全局变量的数目,但本质是对象,不安全。
var myApp={
foo:function(){
//...
},
bar:function(){
//...
}
}
myApp.foo()
3.匿名闭包:IIFE模式,立即执行函数是局部作用域,不污染全局作用域。
var module=(function(){
var _private="安全作用域";
var foo=function(){
console.log(_private)
}
return {
foo
}
})()
module.foo();
module._private;//undefined
4.在立即执行函数中引入依赖:这也是现代模块实现的基石。
var module = (function ($) {
var _$body = $('body')
var foo = function () {
console.log(_$body)
}
return {
foo,
}
})(jQuery)
module.foo()
模块化的好处:
- 避免命名冲突,减少命名空间污染
- 更好的分离,按需加载
- 更高的复用性
- 更容易维护
缺点:
- 由于一个文件被分割成多个文件,造成页面加载时需要更多的
请求数
,而往往我们需要减少发起请求的数量。 - 依赖模糊,拆分的文件往往需要按照一定的顺序引入,这容易造成犯错。
- 难以维护
3.CommonJS
说明:
- 服务器端:模块的加载是运行时
同步加载
的 - 浏览器端:模块需要
提前编译打包
处理
基本语法
暴露模块:
- module.exports=value
- exports.xxx=value
引入模块:
- require(xxx)
注意:
- 当引入的模块是第三方模块,则xxx是模块名,比如(
const jQuery = require('jQuery')
) - 当引入的模块是自定义模块,则xxx是自定义模块的路径,比如(
let myModule = require('./myModule.js')
)
CommonJS常用于NodeJs中。
示例:
创建四个文件:module1.js、 module2.js、module3.js、app.js文件
module1.js
function foo() {
console.log('module1 foo()')
}
module.exports = {
foo,
}
module2.js
module.exports = function () {
console.log('module2()')
}
module3.js
exports.foo = function () {
console.log('module3 foo()')
}
exports.bar = function () {
console.log('module3 bar()')
}
app.js用于引入模块
const module1 = require('./module1') //const { foo } = require('./module1');//使用了es6语法,进行对象解构
const module2 = require('./module2')
const module3 = require('./module3') //const {foo,bar} = require('./module3')
module1.foo()
module2()
module3.foo()
module3.bar()
4.AMD(Asynchronous Module Definition 异步模块定义)
说明:
- 专门用于
浏览器端
,模块的加载是异步
的。 - require.js实现
基本语法
定义模块
- 定义没有依赖的模块:
define(function(){
return 模块
})
- 定义有依赖的模块:
define(['module1','module2'],function(m1,m2){
return 模块
})
引入模块
require(['module1','module2'],function(m1,m2){
使用m1/m2模块
})
require.js使用教程
1.下载require.js, 并引入
- 官网: http://www.requirejs.cn/
- github : https://github.com/requirejs/requirejs
- 将require.js导入项目: js/libs/require.js
2.创建项目结构
|-js
|-libs
|-require.js
|-modules
|-alerter.js
|-dataService.js
|-main.js
|-index.html
3.定义require.js的模块代码
- dataService.js
define(function () {
let msg = 'atguigu.com'
function getMsg() {
return msg.toUpperCase()
}
return {
getMsg}
})
- alerter.js
define(['dataService', 'jquery'], function (dataService, $) {
let name = 'Tom2'
function showMsg() {
$('body').css('background', 'gray')
alert(dataService.getMsg() + ', ' + name)
}
return {
showMsg}
})
4.应用主(入口)js: main.js
(function () {
//配置
requirejs.config({
//基本路径
baseUrl: "js/",
//模块标识名与模块路径映射
paths: {
"alerter": "modules/alerter",
"dataService": "modules/dataService",
}
})
//引入使用模块
requirejs( ['alerter'], function(alerter) {
alerter.showMsg()
})
})()
5.index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AMD示例</title>
</head>
<body>
<script data-main="js/main.js" src="js/libs/require.js"></script>
</body>
</html>
5.CMD (Common Module Definition 通用模块定义)–少用
说明:
- 专门用于浏览器端,模块的加载是
异步
的。 - sea.js实现
- CMD是common.js与AMD的集合
基本语法
定义暴露模块:
- 定义没有依赖的模块
define(function(require,exports,module){
exports.xxx=value
module.exports=value
})
- 定义有依赖的模块
define(function(require,exports,module){
//同步引入依赖模块
var module2 = require('./module2')
//异步引入依赖模块
require.async('./module3',function(m3){
//...
})
//暴露模块
exports.xxx=value
})
引入模块:
define(function(require){
var m1 = require('./module1')
var m3 = require('./module3')
//使用m1/m3
})
sea.js简单使用教程
- 下载sea.js, 并引入
- 官网: http://seajs.org/
- github : https://github.com/seajs/seajs
- 将sea.js导入项目: js/libs/sea.js
- 创建项目结构
|-js
|-libs
|-sea.js
|-modules
|-module1.js
|-module2.js
|-module3.js
|-module4.js
|-main.js
|-index.html
- 定义sea.js的模块代码
- module1.js
define(function (require, exports, module) {
//内部变量数据
var data = 'atguigu.com'
//内部函数
function show() {
console.log('module1 show() ' + data)
}
//向外暴露
exports.show = show
})
- module2.js
define(function (require, exports, module) {
module.exports = {
msg: 'I Will Back'
}
})
- module3.js
define(function (require, exports, module) {
const API_KEY = 'abc123'
exports.API_KEY = API_KEY
})
- module4.js
define(function (require, exports, module) {
//引入依赖模块(同步)
var module2 = require('./module2')
function show() {
console.log('module4 show() ' + module2.msg)
}
exports.show = show
//引入依赖模块(异步)
require.async('./module3', function (m3) {
console.log('异步引入依赖模块3 ' + m3.API_KEY)
})
})
- main.js : 主(入口)模块
define(function (require) {
var m1 = require('./module1')
var m4 = require('./module4')
m1.show()
m4.show()
})
- index.html:
<script type="text/javascript" src="js/libs/sea.js"></script>
<script type="text/javascript">
seajs.use('./js/modules/main')
</script>