Web/11-Node.js/JavaScript模块化:ES6.md

327 lines
8.3 KiB
JavaScript
Raw Normal View History

---
title: JavaScript模块化ES6
publish: true
---
<ArticleTopAd></ArticleTopAd>
## 模块化开发的引入
### JS开发的弊端
JS 在使用时存在两大问题 Node.js 可以很好地避免这两个问题
- 文件依赖比如 a 文件依赖 b 文件b 文件依赖 c 文件 Node.js 中的文件依赖不需要人工维护和人为分析
- 命名冲突js 的各个文件是相互开放的容易导致命名冲突 Node.js 是属于半封闭的状态可以指定哪些内容是开放的哪些内容是封闭的
Node.js 在解决这两个问题时用到的就是模块化开发
### 软件开发中的模块化开发
一个功能就是一个模块多个模块可以组成完整的应用抽离一个模块不会影响其他功能的运行
效果如下
![](http://img.smyhvae.com/20200409_1934.png)
### Node.js 中的模块化开发
Node.js 规定一个 JS 文件就是一个模块模块内部定义的变量和函数默认情况下在外部无法访问
模块内部可以使用 `exports` 对象进行成员导出 使用 `require` 方法导入其他模块效果如下
![](http://img.smyhvae.com/20200409_1932.png)
## ES6模块化的基本语法
### ES6模块化的说明
**依赖模块需要编译打包处理**原因如下
- 1有些浏览器不支持 ES6 的语法写完 ES6 的代码后需要通过`Babel` ES6 转化为 ES5
- 2生成了ES5之后里面仍然有`require`语法而浏览器并不认识`require`这个关键字此时可以用 `Browserify`编译打包 js进行再次转换
推荐学习链接
- <http://es6.ruanyifeng.com/#docs/module>
### 基本语法
**导出模块**
```
export
```
**引入模块**
```
import xxx from '路径'
```
## ES6模块化的使用举例自定义模块
### 1初始化项目
1在工程文件中新建如下目录
```
js
| src
| module1.js
| module2.js
| module3.js
| main.js
index.html
```
2在工程的根目录下新建文件`package.json`内容如下
```json
{
"name": "es6-babel-browserify",
"version": "1.0.0"
}
```
### 2环境配置安装babel browserify等
1安装babel browserify
```bash
npm install babel-cli -g
npm install babel-preset-es2015 --save-dev
npm install browserify -g
```
安装 babel 的详细解释可以参考本人的另外一篇文章[ES6的介绍和环境配置](https://github.com/smyhvae/Web/blob/master/10-ES6/03-ES6%E7%9A%84%E4%BB%8B%E7%BB%8D%E5%92%8C%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE.md)
2新建.babelrc
在根目录下新建文件`.babelrc`输入如下内容
```
{
"presets":[
"es2015"
],
"plugins":[]
}
```
### 3编写代码
1module1.js
```javascript
//暴露模块:采用分别暴露的方式
export function foo1() {
console.log('我是 module1 中的 foo1');
}
export function foo2() {
console.log('我是 module2 中的 foo2');
}
export let arr = [1, 2, 3, 4, 5];
```
2module2.js
```javascript
//暴露模块:采用统一暴露的方式
function fn1() {
console.log('我是 module2 中的 fn1');
}
function fn2() {
console.log('我是 module2 中的 fn2');
}
//统一暴露
export { fn1, fn2 };
```
3module3.js
```javascript
//暴露模块:采用默认暴露的方式。
//默认暴露的方式可以暴露任意数据类型,暴露的是什么数据,接收到的就是什么数据
//语法格式export default value;
export default () => {
console.log('我是 module3 中 default 方式暴露的函数');
};
```
这里我们采取了一种新的暴露方式默认暴露在暴露时加上了`default`这个关键字代码里暴露了一个箭头函数稍后我们注意在main.js里是怎么引入module3.js的
注意我们只能写一次 default也就是说只能进行一次默认暴露
4module4.jsdefault方式暴露多个属性
```javascript
//暴露模块:采用默认暴露的方式。
//默认暴露的方式可以暴露任意数据类型,暴露的是什么数据,接收到的就是什么数据
//语法格式export default value;
export default {
name: '我是 module4 中 default 方式暴露的属性 name',
foo() {
console.log('我是 module4 中 default 方式暴露的函数 foo');
}
}
```
这里我们依旧采取了默认暴露的方式只能写一次 default代码里暴露了一个对象对象里存放了一个属性一个方法稍后我们注意在main.js里是怎么引入module4.js的
如果我想暴露多个属性多个对象怎呢很简单把你想要暴露的所有内容都放在default里包成一个对象你看module4.js就是如此 同时暴露了多个属性&方法
5main.js
这个是主模块现在我们来看一下它如何引入上面的四个模块
```javascript
//主模块。引入其他的模块
import { foo1, foo2 } from './module1'; //采用解构赋值的形式进行导入。注意,括号里的对象名,要和 module1 中的对象名一致。
import { fn1, fn2 } from './module2'; //采用解构赋值的形式进行导入。注意,括号里的对象名,要和 module2 中的对象名一致。
import myModule3 from './module3'; //module3 模块是采用 default 方式进行暴露的myModule3 这个名字是我随便起的
import myModule4 from './module4'; //module4 模块是采用 default 方式进行暴露的myModule4 这个名字是我随便起的
//调用module1、module2中的内容
foo1();
foo2();
fn1();
fn2();
//调用module3中的内容
myModule3();
//调用module4中的内容
console.log(myModule4.name); //module4中的属性
myModule4.foo(); //module4中的方法
```
我们可以看出具体请看注释非常重要
- module1和module2是采用**常规暴露**的形式在引入它们时模块名要一致而且要求用**对象解构赋值**的形式而不是用 `import myModule from ...`这种形式否则会报错 undefined
- module2和module3是采用**默认暴露**的形式在引入它们时模块名随便起
6index.html
在这里引入main.js即可
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script src="dist/main.js"></script>
</body>
</html>
```
### 4编译转换
如果我们不进行转换而是直接在 index.html 中加载 js/src/main.js是会报错的
接下来我们就进行转换
1利用 babel ES6 转换为 ES5
```
babel src -d build //build目录会自动生成
```
上方命令的意思是`src`目录下的所有ES6文件转化为ES5文件并放在`build`目录下`build`目录会被自动创建
转化成ES5之后我们发现如果直接在 index.html 中加载`build`目录下的ES5文件也是会报错的因为浏览器不认识`main.js`里的`require`关键字
![](http://img.smyhvae.com/20180414_1410.png)
于是我们还要进行一次转换
2利用`Browserify`编译打包 `build`目录下的 ES5 文件
```bash
browserify build/main.js -o dist/main.js //dist目录需要手动创建
```
dist/main.js就是我们需要引入到 index.html 里的文件
以后我们每次修改完ES6的代码就要执行上面的两个命令重新生成新的js文件
运行效果
![](http://img.smyhvae.com/20180414_1615.png)
工程文件
- [2018-04-13-ES6Demo.rar](https://download.csdn.net/download/smyhvae/10348940)
## ES6模块化的使用举例引入第三方模块
下载 jQuery
```
npm install jquery@1 //下载jQuery 1.X 的版本里最新的
```
在main.js 中引入上面的 jQuery
```
import $ from 'jQuery';
```
然后我们就可以通过`$`这个符号去写jQuery的代码了