模块无法导入_模块化规范介绍

什么是模块?

模块就是一个JS文件,它实现了一部分功能,并隐藏自己的内部实现,同时提供了一些接口供其他模块使用。

模块有两个核心要素:**隐藏**和**暴露**:

隐藏的,是自己内部的实现

暴露的,是希望外部使用的接口

任何一个正常的模块化标准,都应该默认隐藏模块中的所有实现,而通过一些语法或api调用来暴露接口。

模化开发,是JS通向大型应用的基石,学习好模块化,便具备了编写大型应用的基本功。

在学习模块化之前,首先认识两个重要的概念:**模块的导出**和**模块的导入**。

模块的导出:暴露接口的过程即模块的导出。

模块的导入:当通过某种语法或api去使用一个模块时,这个过程叫做模块的导入。

当需要使用一个模块时,使用的是该模块暴露的部分(导出的部分),隐藏的部分是永远无法使用的。

模块化规范:

1、CommonJS

在nodejs中,由于有且仅有一个入口文件(启动文件),而开发一个应用肯定会涉及到多个文件配合,因此,nodejs对模块化的需求比浏览器端要大的多。

由于nodejs刚刚发布的时候,前端没有统一的、官方的模块化规范,因此,它选择使用社区提供的CommonJS作为模块化规范。

学习CommonJS需要安装nodejs。

安装nodejs官网地址:https://nodejs.org/zh-cn/

CommonJS使用```exports```导出模块,```require```导入模块。

12cdd5d357c2ba3129116efc45febf1b.png

d5f700fc4c00ec6dd68d061dca08f359.png

具体规范如下:

1. 如果一个JS文件中存在```exports```或```require```,该JS文件是一个模块

2. 模块内的所有代码均为隐藏代码,包括全局变量、全局函数,这些全局的内容均不应该对全局变量造成任何污染

3. 如果一个模块需要暴露一些API提供给外部使用,需要通过```exports```导出,```exports```是一个空的对象,你可以为该对象添加任何需要导出的内容

4. 如果一个模块需要导入其他模块,通过```require```实现,```require```是一个函数,传入模块的路径即可返回该模块导出的整个内容

34558089b05924b07476c353b0c08134.png

要运行CommonJS,需要在入口文件处打开终端。nodejs直接运行某个js文件,该文件被称之为入口文件。

浏览器不支持CommonJS:

当想要把CommonJS放到浏览器端时,就遇到了一些挑战

1. 浏览器要加载JS文件,需要远程从服务器读取,而网络传输的效率远远低于node环境中读取本地文件的效率。由于CommonJS是同步的,这会极大的降低运行性能

2. 如果需要读取JS文件内容并把它放入到一个环境中执行,需要浏览器厂商的支持,可是浏览器厂商不愿意提供支持,最大的原因是CommonJS属于社区标准,并非官方标准

AMD和CMD规范,有效的解决了浏览器模块化的问题。

2、AMD规范:

全称是Asynchronous Module Definition,即异步模块加载机制

require.js实现了AMD规范 (需要下载require.js)

需要引入require.js文件,

39069bba97488289faf897cf2c6eb920.png

在AMD中,导入和导出模块的代码,都必须放置在define函数中

fd8e14c0223497d2c2f55f04c7d440c8.png

977856d12234974c73fbf6eadc07ae8b.png

cbc87adc014c573d09f2ad2933727129.png

ab2624dd64c246ffe412ac7879af1639.png

3、CMD规范:

全称是Common Module Definition,公共模块定义规范

sea.js实现了CMD规范 (需要下载sea.js)

需要引入sea.js文件,

8a86a9d018f2aaffdb71fb2b9ea8bb6d.png

在CMD中,导入和导出模块的代码,都必须放置在define函数中

840a36677ddf003c3c65ae3e29b7a9a9.png

47575dcead58f25123570bce2335b97e.png

714d289df60c691f8ec74444b14c97ec.png

4752d1c4f1a7ddcd552a8edbcb173aca.png

4、ES6模块化官方标准:

ECMA组织参考了众多社区模块化标准,终于在2015年,随着ES6发布了官方的模块化标准,后成为ES6模块化。

ES6模块化具有以下的特点:

1. 使用依赖**预声明**的方式导入模块

1. 依赖延迟声明

1. 优点:某些时候可以提高效率

2. 缺点:无法在一开始确定模块依赖关系(比较模糊)

2. 依赖预声明

1. 优点:在一开始可以确定模块依赖关系

2. 缺点:某些时候效率较低

2. 灵活的多种导入导出方式

3. 规范的路径表示法:所有路径必须以./或../开头

ES6中的模块导入导出分为两种:

d33e7afbe9e789bce40d21542c1bd9a0.png

1. 基本导入导出:

基本导出可以有多个,每个必须有名称;基本导出的语法如下:export 声明表达式 或 export {具名符号}。

b15312a7ce5a35fe27204997c2c18687.png

基本导入,导入任何其他模块,导入代码必须放置到所有代码之前;对于基本导出,如果要进行导入,使用下面的代码:import {导入的符号列表} from "模块路径"。

fd92795a86032bb7929e29a19fa8b8b9.png

36b92073aa5282cfce6fe09d4df7cee2.png

注意以下细节:

- 导入时,可以通过关键字```as```对导入的符号进行重命名

- 导入时使用的符号是常量,不可修改

- 可以使用*号导入所有的基本导出,形成一个对象

2. 默认导入导出:

每个模块,除了允许有多个基本导出之外,还允许有一个默认导出。

默认导出:

默认导出类似于CommonJS中的```module.exports```,由于只有一个,因此无需具名。

具体的语法是:export default 默认导出的数据 或 export {默认导出的数据 as default}。

由于每个模块仅允许有一个默认导出,因此,每个模块不能出现多个默认导出语句。

f65fe3d228ef24b256096d64b565d4c0.png

默认导入:

需要想要导入一个模块的默认导出,需要使用下面的语法:import 接收变量名 from "模块路径" 。

441d462fa8a2eaefe97fc6ed1824dbcd.png

f7ca5d682e78475c7f0c361e38124616.png

如果希望同时导入某个模块的默认导出和基本导出,可以使用下面的语法:import 接收默认导出的变量, {接收基本导出的变量} from "模块路径"。

注:如果使用*号,会将所有基本导出和默认导出聚合到一个对象中,默认导出会作为属性default存在。

ES6模块化的其他细节:

1. **尽量导出不可变值**

当导出一个内容时,尽量保证该内容是不可变的(大部分情况都是如此)

因为,虽然导入后,无法更改导入内容,但是在导入的模块内部却有可能发生更改,这将导致一些无法预料的事情发生

2. **可以使用无绑定的导入用于执行一些初始化代码**

如果我们只是想执行模块中的一些代码,而不需要导入它的任何内容,可以使用无绑定的导入:import "模块路径"

3. **可以使用绑定再导出,来重新导出来自另一个模块的内容**

有的时候,我们可能需要用一个模块封装多个模块,然后有选择的将多个模块的内容分别导出,可以使用下面的语法轻松完成:export {绑定的标识符} from "模块路径"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值