一、Module出现的原因
1.1、最初引入js文件的方式(原始引入与立即调用函数表达式方式)
原始方式

将1.js以及2.js文件引入到html文件中,最开始的方式为:
1.js
2.js
exer.html
<!-- 使用script标签来引入js文件 -->
<script src="./modules/1.js"></script>
<script src="./modules/2.js"></script>
<script>
console.log(`num1=${num1}`)
console.log(`num2=${num2}`)
</script>

说明:这种引入js的方式有很多弊端,例如大量的变量定义存在于一个上下文中,并且若是有多个js文件都需要进行一个个引入!
稍微优化后的引入方式:通过立即调用函数表达式
使用该种方式能够将对应想要暴露出去的对象或变量放置到全局变量window对象中:对于全局变量定义形成可控
1.js
(function () {
const num1 = 10;
const num11 = 11;
//仅仅暴露出去num11
window.num11 = num11;
})();
2.js
(function () {
const num2 = 100;
//暴露出去num2
window.num2 = num2;
})();
exer.html
<!-- 使用script标签来引入js文件 -->
<script src="./modules/1.js"></script>
<script src="./modules/2.js"></script>
<script>
//暴露出来的仅仅只有两个变量num11,num2,对于num1并没有暴露出来,存在于闭包中
console.log(`num11=${num11}`)
console.log(`num2=${num2}`)
console.log(`num1=${num1}`)
</script>

**好处:**对于我们想要暴露出去的指定对象或变量能有很好的可控性,但是这就需要你每个js文件都要写()()立即函数表达式。
缺点(待解决问题):模块化的问题,对于某个模块想要使用另一个模块中的指定对象就需要通过window的全局变量来操控,这就对项目中模块与模块之间使用出现了很大的问题。需要出现一种模块系统来进行解决问题,消除全局变量以及管理加载顺序等等,这就需要使用到了Module模块系统,ES6就推出了该系统!!!
1.2、使用Module模块系统管理(初次使用)
下面是通过使用Module模块系统管理:使用export xxx 以及 import xxx进行使用
1.js
const num1 = 10;
export default num1;
2.js
// 引入模块,并输出变量
import num1 from './1.js'
console.log(`num1=${num1}`);
const num2 = 100;
//导出num2
export default num2;
exer.html
<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
// 引入模块得到num2
import num2 from './modules/2.js'
console.log(`num2=${num2}`);
//测试输出其他模块
console.log(num1);
</script>

二、Module模块方式与使用前提条件
2.1、引入Module模块方式(两种)
方式一:通过script标签来引入模块,该种方式不能够得到对应的模块输出内容
<script src="./modules/2.js" type="module"></script>
方式二:使用import方式,可以获取到对应模块导出的内容
import num2 from './modules/2.js'
2.2、前提条件
ES6出现模块系统来方便进行管理!ES Module就是RequireJS seaJS的原生版本了,就是进行模块管理的!
使用Module模块系统的前提条件:
需要搭建服务器的环境,让Module模块系统能够进行正常的执行。(本地直接打开页面是不行的,如使用file协议打开的就会出现下面的报错)

对于搭建服务器的环境比较简单的方式使用vscode插件:live Server即可!!!
三、Module的两种导出与导入
导出(export)的东西可以被导入(import),并被访问到!
注意:一个模块没有导出也可以将其导入,被导入的代码都会执行一遍,也仅仅会执行一遍!
方式一:export default导出与import导入(只能单个)
多次引入相同的模块:只会执行一次该js文件
2.js
const num = 10;
console.log(num);
// 导出
export default num;
测试:
<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
// 多次引入同一个模块中的js文件,该文件只会执行一次!
import num from './modules/2.js';
import num1 from './modules/2.js';
import num2 from './modules/2.js';
</script>

基本要求(3点)
1、一个模块中只能有一个export default,否则会报语法错误:Uncaught SyntaxError: Identifier '.default' has already been declared
2、导出的类型可以为任意类型(基本类型、引用类型都可),可以写成表达式形式(或者匿名表达式)也是可以的。
3、配合引用import时对于导出的值可以随意起别名。
测试:
2.js
const num = 10;
console.log(num);
//测试2:分别为基本类型、匿名表达式、对象
export default num;
// export default function () { console.log("hello"); }
// export default { name: 'changlu', age: 18 };
exer.html
<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
// 多次引入同一个模块中的js文件,该文件只会执行一次!
import num from './modules/2.js';
console.log(num);
</script>
方式二:export导出与import引入(单、多个)
基本使用
export=>import:可以导出单个或者多个,导出时不能使用别名必须使用导出时的名称
注意:
导入时应当与导出时的名称一致并且需要被**{}包裹**。
不能导出匿名函数、箭头函数等一些没有变量名的!
导出单个的方式
// 方式一:通过声明形式导出
export const num = 2; //对应导入:import {num} from './module/2.js'
// 方式二:直接导出变量形式
export { num }; //对应导入:import {num} from './module/2.js'
导出多个方式
2.js
const num = 1;
const str = 'changlu';
const obj = { name: 'cl' }
// 导出多个
export { num, str, obj };
方式一:允许一个个单独导出
<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
// 多次单独导出指定的属性
import { num } from './modules/2.js';
import { str } from './modules/2.js';
import { obj } from './modules/2.js';
console.log(num, str, obj);
</script>
导出导入时起别名
介绍
无法起别名情况:声明式的,如:export const num = 1,不能取别名!
可以起别名情况:导入与导出都可以设置别名,如export {num as bieming}或import {num as bieming} from 'xxx'
示例
2.js
const num = 10;
export { num };
exer.html
<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
// 起了别名之后,别名num1才有对应的值
import { num as num1 } from './modules/2.js';
console.log(num1);
console.log(num);
</script>

整体导入(导入到一个对象中,* as obj)
示例:
2.js
const num = 10;
const str = 'changlu';
const arr = [1, 2, 3];
// 同时导出多个
export { num, str, arr };
exer.html
<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
// 整体多个值导入到一个对象中
import * as obj from './modules/2.js';
console.log(obj);
//可直接通过键来获取到对应的值
console.log(obj.arr);
console.log(obj.num);
console.log(obj.str);
</script>

export与eport default同时导出
说明:也就是说两种导出方式能够一起使用,只不过有限制就是export default一个模块中只能够使用一次!若是一起导出时,导入指定模块需要将export default先导入,如下!
2.js
const num = 10;
const str = 'changlu';
const arr = [1, 2, 3];
//使用export导出多个
export { num, str, arr };
//使用export default导出1个
export default 30;
exer.html
<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
// 注意了若是引入的模块中使用了export default,那么就必须先引入该expert default的值
import num, * as obj from './modules/2.js';
//输出export default导出的值
console.log(`export default的值为:${num}`);
//输出export导出的值
console.log("export导出的对象集合为:");
console.log(obj);
console.log(obj.arr);
console.log(obj.num);
console.log(obj.str);
</script>
