20.模块化

 

1.模块化

模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来

2.模块化的好处:

  • 防止命名冲突
  • 代码复用
  • 高维护性

3.模块化规范产品:

ES6 之前的模块化规范有:

  • CommonJS => NodeJS、 Browserify
  • AMD => requireJS
  • CMD => seaJS

4.ES6 模块化语法

模块功能主要由两个命令构成: exportimport

  • export 命令用于规定模块的对外接口
  • import 命令用于输入其他模块提供的功能

5.ES6 模块化跨域问题

Es6模块化出现跨域问题解决方法

VSCode 安装 Live Server 插件

右键选择 Open with Live Server 打开 html 文件

6.ES6 模块对外暴露方式

ES6 模块对外暴露方式:

  • 分别暴露
  • 统一暴露
  • 默认暴露

(1) module1: m1.js

1
2
3
4
5
6
// 分别暴露
export let student = 'Tom';

export function learn() {
console.log("studying");
}

(2) module2: m2.js

1
2
3
4
5
6
7
8
// 统一暴露
let student = "Jerry";

function play() {
console.log("playing");
}

export {student, play};

(3) module3: m3.js

1
2
3
4
5
6
7
// 默认暴露
export default {
student: "Danny",
walk: function() {
console.log("walking");
}
}

7.ES6 模块导入方式

ES6 模块导入方式:

  • 通用方式
  • 解构赋值形式
  • 简便形式: 只适用于导入 默认暴露 方式的模块

(1) 通用导入方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ES6 模块导入方式</title>
</head>
<body>
<script type="module">
// 1. 通用的导入方式
// (1) 引入 m1.js 模块内容
import * as m1 from "./src/js/m1.js";
console.log(m1);
/**
* Module {Symbol(Symbol.toStringTag): 'Module'}
* learn: ƒ learn()
* student: "Tom"
* Symbol(Symbol.toStringTag): "Module"
* get learn: ƒ ()
* set learn: ƒ ()
* get student: ƒ ()
* set student: ƒ ()
*/
console.log(m1.student); // Tom
m1.learn(); // studying

// (2) 引入 m2.js 模块内容
import * as m2 from "./src/js/m2.js";
console.log(m2);
/**
* Module {Symbol(Symbol.toStringTag): 'Module'}
* play: ƒ play()
* student: "Jerry"
* Symbol(Symbol.toStringTag): "Module"
* get play: ƒ ()
* set play: ƒ ()
* get student: ƒ ()
* set student: ƒ ()
*/
console.log(m2.student); // Jerry
m2.play(); // playing

// (3) 引入 m3.js 模块内容
import * as m3 from "./src/js/m3.js";
console.log(m3);
/**
* Module {Symbol(Symbol.toStringTag): 'Module'}
* default: Object
* student: "Danny"
* walk: ƒ ()
* [[Prototype]]: Object
* Symbol(Symbol.toStringTag): "Module"
* get default: ƒ ()
* set default: ƒ ()
*/
console.log(m3.default.student); // Danny
m3.default.walk(); // walking
</script>
</body>
</html>

(2) 解构赋值形式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ES6 模块导入方式</title>
</head>
<body>
<script type="module">
// 2.解构赋值形式
import {student, learn} from "./src/js/m1.js";
console.log(student); // Tom
learn(); // studying

import {student as st, play} from "./src/js/m2.js";
console.log(st); // Jerry
play(); // playing

import {default as m3} from "./src/js/m3.js";
console.log(m3); // {student: 'Danny', walk: ƒ}
console.log(m3.student); // Danny
m3.walk(); // walking
</script>
</body>
</html>

(3) 简便形式: 只适用于导入 默认暴露 方式的模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ES6 模块导入方式</title>
</head>
<body>
<script type="module">
// 3.简便形式: 只适用于导入 默认暴露 方式的模块
import m3 from "./src/js/m3.js";
console.log(m3); // {student: 'Danny', walk: ƒ}
console.log(m3.student); // Danny
m3.walk(); // walking
</script>
</body>
</html>

(4) 使用 <script> 标签导入模块

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ES6 模块化</title>
</head>
<body>
<script src="./src/js/app.js" type="module"></script>
</body>
</html>

app.js

1
2
3
4
5
6
7
8
9
10
// 入口文件

// 模块引入
import * as m1 from "./m1.js";
import * as m2 from "./m2.js";
import * as m3 from "./m3.js";

console.log(m1); // Module {Symbol(Symbol.toStringTag): 'Module'}
console.log(m2); // Module {Symbol(Symbol.toStringTag): 'Module'}
console.log(m3); // Module {Symbol(Symbol.toStringTag): 'Module'}

8.使用 babel 对 ES6 模块化代码进行转换

有时为了兼容,需要将 ES6 模块化代码转换为 ES5 语法,可以使用 babel 将 ES6 模块化代码转换为 ES5 语法

进入项目目录

(1) npm 初始化目录

1
npm init --yes

(2) 安装依赖包

1
npm i babel-cli babel-preset-env browserify -D

(3) 编译:

如果是局部安装,命令需要加 npx,如果是全局安装,就不需要加 npx 了

1
npx babel [source_dir] -d [target_dir] --presets=babel-preset-env
1
npx babel src/js -d dist/js --presets=babel-preset-env

(4) 打包

1
npx browserify [source_js] -o [target_js]
1
npx browserify dist/js/app.js -o dist/bundle.js

(5) 引入模块

home.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!--
1. 安装工具 npm i babel-cli babel-preset-env browserify(webpack) -D
2. 编译 npx babel src/js -d dist/js --presets=babel-preset-env
3. 打包 npx browserify dist/js/app.js -o dist/bundle.js
-->
<script src="dist/bundle.js"></script>
</body>
</html>

(6) 运行

右键 Open with Live Server 打开 home.html 文件,app.js 的 console.log() 语句,console 输出:

1
2
3
Object
Object
Object

9.ES6 模块化引入 npm 包

npm jquery 包为例

安装 npm jquery

1
npm i jquery

app.js

1
2
import $ from "jquery"; // const $ = require("jquery");
$("body").css("background", "pink");

重新编译打包,右键 Open with Live Server 打开 home.html 文件,实现了对<body>标签的背景颜色的修改