JavaScript模块化
什么是模块化?
即将一个复杂的程序依据一定的规则(规范)封装成几个块(文件),并用规定语法将其组合在一起,块的内部数据/实现是私有的,只是向外部暴露一些接口(方法)与外部其他模块通信
以前的代码
全局模式
function foo(){
}
function abc(){
}
问题: 所有的函数都被绑定在了window
上,容易产生命名冲突和产生对window
的污染
namespace模式
将函数或者数据绑定在对象上
let obj = {
k: 'asd',
foo(){
console.log(this.k)
},
abc(){
}
}
问题: 对象中的数据可以随意被修改,所以数据不安全
IIFE(Immedicately-invoked-function-expression)
该方法就是利用函数的作用域和即使函数的特性
(function(window){
function foo(){
console.log('ooo')
}
window.module={foo}
})(window);
-----------------------------
module.foo();
或者
(function(window){
function foo(){
console.log('ooo')
}
window.module=foo
})(window);
-----------------------------
module();
IIFE就是现代化模块化的基石
模块化的好处
- 避免命名冲突
- 根据功能点进行更好的分离
- 更高的复用性
- 高可维护性
但是以此同时就出现了问题
- 一个页面需要引入多个js文件,如果多个文件之间有依赖关系,先后顺序的错误就会导致报错
- 请求过多
- 依赖模糊
- 难以维护
这时候我们就需要引入一种模块化的规范来避免这种问题,下面我们来看看有哪些模块化规范
模块化的规范
- CommonJS(nodejs就是基于这种规范)
- AMD (用的少)
- CMD(阿里的人写的。用的少)
- ES6
CommonJS
说明:
- 每一个文件都是一个模块
- 服务器端:模块的加载是运行时同步加载的
- 浏览器端:需要自己编译打包将所有的模块js合并到一个js中
定义模块:
module.exports={}
---
expoets.foo = function(){
}
exports.n = 2
引入模块:
let module1 = require(..)
// 这里的..
// 引入第三方的包 直接写包名
// 引入自己写的js 写路径
服务器端例子:
先创建项目结构
-modules
--module1.js
--module2.js
--module3.js
-app.js
-package.json
module1.js
module.exports = {
foo(){
console.log(`'module1's foo()`)
}
}
module2.js
exports.foo = function(){
console.log(`'module2's foo()`)
}
exports.abc = function(){
console.log(`'module2's abc()`)
}
module3.js
module.exports = function(){
console.log(`'module3's foo()`)
}
app.js
let module1 = require('./modules/module1.js')
let module2 = require('./modules/module2.js')
let module3 = require('./modules/module3.js')
module1.foo()
module2.foo()
module2.abc()
module3()
package.json
{
name: 'applicationname',// 这里写项目名字,不能有大写字母,不能有中文
version: '1.0.0'
}
可以使用npm init
生成该文件
客户端例子:
结构树如下
-test
--dist
--src
---module1.js
---module2.js
---module3.js
---app.js
--index.html
--package.json
js代码如上
下载编译工具
npm install browserify -g # 全局安装
npm install browserify --save-dev # 开发依赖,在上线阶段不需要此工具了
使用该工具
browserify src/app.js -o dist/budle.js
index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<title>title</title>
</head>
<body>
<script src='./dist/budle.js'></script>
</body>
</html>
AMD
说明:AMD((Asynchronous Module Definition))专门用户浏览器端,模块的加载是异步的
此规范依赖于一个Require.js
基本语法:
定义模块:
// 没有依赖其他模块
define(function(){
return 模块
})
// 定义有依赖的模块
define(['module1','module2'],function(m1,m2){
return 模块
})
引入模块
require(['module1','module2'],function(m1,m2){
使用m1/m2
})
requirejs(['module1','module2'],function(m1,m2){
使用m1/m2
})
例子:
目录结构
-test
--js
---libs
----require.js//这是引入的第三方js
---modules
----module1.js
----module2.js
----modlue3.js
---main.js
--index.html
mudule1.js
define(function(){
lett msg = 'module1';
function foo(){
console.log(msg)
}
return {foo}
})
module2.js
define(['module1'],function(m1){
let msg = 'module2.js'
function foo(){
console.lopg(msg,m1.foo())
}
return {foo}
})
main.js
(function(){
require.config({
baseUrl: 'js/',
path: {
module1: './modules/module1.js',
module2: './modules/module2.js'
jquery: './libs/jquery.js'//引入第三方库,不是所有的第三方库都支持AMD语法
}
})
requirejs(['module1','module2'],function(m1,m2){
m1.foo();
})
})()
页面中只要引入该标签即可
<script data-main="js/main.js" src=js/libs/require.js></script>
ES6规范
说明:该规范也需要编译打包处理,先使用babel
将ES6转化为ES5,然后使用browserify
将其并为一个js文件
基本语法:
导出模板:
export function foo(){
}
export function abc(){
}
------------------------------------------------------------------------------------------------------
function foo(){
}
function abc(){
}
export {foo,abc}
------------------------------------------------------------------------------------------------------
export default {
function foo(){
}
function abc(){
}
}
引入模块:
// 常规导出,这边用对象接
import {} from '路径' //自己的js
// 默认导出,这边用变量来接
impoet module from '路径'
例子:
项目结构
-test
--js
---dist
---build
---src
----module1.js
----module2.js
----module3.js
----main.js
--index.html
--.babelrc
--package.json
安装依赖
npm install browserify --save-dev
npm install babel-cli -g
npm install babel-preset-es2015 --save-dev
创建.babelrc
rc就是run control运行时控制文件
{
"presets":["es2015"]
}
module1.js
export function foo(){
}
export function abc(){
}
module2.js
function f1(){
}
function f2(){
}
export {f1,f2}
module3.js
export default {
function d1(){
}
function d2(){
}
}
main.js
import {foo,abc} from './module1.js'
import {f1,f2} from './module2.js'
import module3 from './module3.js'
foo();
abc();
f1();
module3.d1();
module3.d2();
es6转es5
babel js/src -d js/build
这里如果出现这个错误:
babel : 无法加载文件 C:\Users\win\AppData\Roaming\npm\babel.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/ go.micros
那么你输入以下命令一定是这样的
get-ExecutionPolicy
# restricted
这时候,先使用管理员身份打开Windows Powershell
然后输入以下命令
set-ExecutionPolicy RemoteSigned
然后输入y回车
合并文件
browserify js/build/main.js -o js/dist/bundle.js
index.html
导入js
<script src="js/src/dist/bundle.js"></script>