24:模块化开发

一、开发方式的演变

  1. 最早:一个 js 文件
    • 每一个 html 文件对应一个 js 文件
  2. 后来:把一个项目内部的重复功能提取出来
    • 写成一个单独的 js 文件
  3. 再后来:决定按照功能拆分出一个一个的文件
    • a.js:专门做顶部导航栏各种功能
    • b.js:专门做二级菜单
    • c.js:专门做搜索引擎
    • d.js:左侧边栏
    • e.js:轮播图
    • 最后在每一个页面准备一个整合的 js 文件,在引入这个整合的js文件的script标签中添加一个type="module"属性
    • 就是专门用来组合这个页面使用了多少个 js 文件模块
  4. 此时, 我们管每一个 js 文件叫做一个 模块
    • 页面的完整功能, 就是由一个一个的模块来完成的

二、什么是模块化开发

  1. 模块化开发:是一种项目的构架模式,这种构架模式让 js 代码重用性变得非常高,让项目构架的一些复杂问题全部得以解决。
    • 例如,一个html文件内不会再出现多个script标签,我们只要用一个script标签引入整合后的文件就可以了。
    • 一个模块就是实现特定功能的文件,有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块
  2. 模块化开发的特点:
    • 为了减少系统耦合度,提高内聚,减少资源依赖
    • 便于维护,功能复用性更强
    • 解决独立作用域、依赖管理、api暴露、按需加载与执行、安全合并等问题

三、常见的模块化规范

  1. AMD规范:第三方规范,依赖前置,规范化文件:require.js。
    • 特点 : 前期消耗网络资源大,后期运行效率高
    • 参考文档
  2. CMD规范:第三方规范,按需加载,规范化文件:sea.js。
    • 特点:整个执行消耗曲线比较平缓
  3. CommonJS规范:Node.js的官方模块化规范
  4. ES6规范:ECMAScript的官方模块化规范

四、ES6模块化规范

  • ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
  • ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。

4.1 使用环境:

- 使用了ES6模块化规范的页面必须处于服务器内
- VSCode的服务器插件:`Live Server`,安装(install),重启VSCode,在底部状态栏,点击`go Live`,启动服务器
- 在html文件中,右键选择 `open with live server`
- 注意:引入使用了ES6模块规范的js文件的`script`标签,需添加`type="module"`属性

4.2 注意事项

- 每一个 js 文件,都是一个独立的文件作用域
- 该文件内的所有变量和方法,都只能在这个文件内使用

4.3 ES6模块化语法

  1. 使用export关键字,规定模块的对外接口;使用import关键字,输入其他模块提供的功能接口
  2. 导出语法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 定义模块export语法:(module.js文件)
export const a = 10;

const b = 20;
export {b};

const c = "admin"
export {c as name};

// 或者

export {a,b,c};
export {a as num1, b as num2, c as name};
export default {num1:a, num2:b, name:c}
  1. 导入语法
1
2
3
4
5
6
7
8
9
10
// 导入模块import语法:(main.js文件)
import {a} from "./module.js";
import {b} from "./module.js";
import {c} from "./module.js";
import {a,b,c} from "./module.js";
import {num1,num2,num3} from "./module.js";
import * as mObj from "./module.js";
// 或者
import {num1 as n1, num2 as n2, num3 as n3} from "./module.js";
import obj from "./module.js";
  1. 注意:
    1. exportimport关键字,只能存在于顶层作用域内,不能存在局部或块级作用域
    2. 在ES6的所有语法中,所有语法自动处在严格模式下
    3. export是声明关键字,声明一个对外接口
    4. export声明的接口必须和模块内部的变量建立一一对应的关系
    5. export声明的接口与对应的值是动态绑定,即可以拿到模块内部实时修改的值
    6. exportimport时,都可以使用as关键字,重命名接口
    7. 使用default关键字,设置默认接口,一个模块中只允许出现一次default
    8. import在使用接口时,必须将接口放在花括号内,除非export暴露接口时使用了default关键字
    9. import加载的接口是只读的,不允许被修改,如果接口是对象,可以修改属性
    10. import具有提升效果
    11. 由于import是静态执行,所以不能使用表达式和变量
    12. import后没有接收接口,会执行整个模块文件
    13. 可以使用通配符*加载整个模块的接口(需要配合as使用),返回一个模块对象