ES6 模块导入导出的介绍及示例

目录

1. export

1.1 命名导出的三种写法

1.1.1 export 可以直接写在模块文件末尾,按需导出

1.1.2 每个对外暴露的变量前加上 export

1.1.3 给导出的 export 内容使用 as 换个名字

1.2 命名导出的注意事项

1.3 默认导出(export default)

2. import

2.1 导入整个文件对象

2.2 导入部分接口

2.3 import 解决命名冲突的问题

2.4 import 命令的特点

2.4.1 只读属性

2.4.2 单例模式

2.4.3 静态执行特性

2.5 导入默认接口 default

2.6 动态导入

2.7 动态模块的应用

2.7.1 按需加载

2.7.2 条件加载

2.7.3 动态模块路径

2.8 import 注意事项

3. export import 复合使用

3.1 复合使用时的基本语法

3.2 一些栗子


  • 前言:CommonJS、AMD、CMD、ES6 都是模块化解决方案,基本概念如下:
  1. CommonJS 规范主要用于服务端编程,加载模块是同步的;不适合在浏览器环境,因为浏览器资源是异步加载的,存在阻塞加载,也因此有了 AMD、CMD
  2. AMD 规范在浏览器环境中,异步加载模块,而且可以并行加载多个模块
  3. CMD 规范与 AMD 规范很相似,都用于浏览器编程,依赖就近,代码更简单
  4. ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为 浏览器 和 服务器 通用的模块解决方案

  • ES6 导入导出功能,主要有两个命令:export 和 import
  1. export 命令:规定模块对外导出的接口
  2. import 命令:导入其他模块暴露的接口

1. export

1.1 命名导出的三种写法

1.1.1 export 可以直接写在模块文件末尾,按需导出

function sayHello() {
  console.log("module - 1 : sayHello函数");
}

let people = {
  hair: "color",
};

let firstName = "lili";

let lastName = "wang";

export { sayHello, people, firstName };
  • 打印结果如下,没有导出 lastName,因此打印结果没有它 


1.1.2 每个对外暴露的变量前加上 export

  • 这种写法一般用在 项目的公共自定义方法里,举个栗子:
  1. 假设我现在再写一个 vue 项目,我会在 vue 根目录下定义 utils/common.ts,该文件用于存放各种公共方法,比如判断空值、处理视频格式等等
  2. 在 common.ts 每个方法之前,加上 export
  3. 在不同 .vue页面文件中,按需引入需要的 export 方法
export function sayHello() {
  console.log("module - 1 : sayHello函数");
}

export let people = {
  hair: "color",
};

export let firstName = "lili";

export let lastName = "wang";

1.1.3 给导出的 export 内容使用 as 换个名字

  • 如果不想暴露 模块内部私有变量 的名字,可以通过 as 来进行重命名
  • sayHello 可以用不同的名字输出两次
function sayHello() {
  console.log("module - 1 : sayHello函数");
}

let people = {
  hair: "color",
};

let firstName = "lili";

let lastName = "wang";

export {
  people,
  firstName,
  sayHello as peopleSayHello,
  sayHello as liliSayHello,
};

1.2 命名导出的注意事项

  • export 命令,可以出现在模块的任何位置,只要处于模块最外层就可以
  • 针对上面的代码来说,不能处于 sayHello 函数中,会报错
  • 举个错误示例:
function sayHello() {
  console.log("module - 1 : sayHello函数");
  export {
    people,
    firstName,
    sayHello as peopleSayHello,
    sayHello as liliSayHello,
  };
}


  • export 语句输出的接口,与其模块内对应的值,是动态绑定关系
  • 即通过 export 拿的值是模块内部实时的值
  • 举个栗子:
export var foo = "bar";
setTimeout(() => (foo = "baz"), 500);


1.3 默认导出(export default)

  • 在一个文件或模块中,export、import 可以有多个,export default 仅有一个
  • 通过 export 方式导出的成员,在导入时要加 { },export default 则不需要
  • export default 向外暴露的成员,可以使用任意变量来接收
export { sayHello, people, firstName };

export default {
  name: "default",
};

2. import

  • import 大括号里的变量名,必须与被导入模块对外接口的暴露 export 对象名一致

2.1 导入整个文件对象

  • impot 所有(*),使用 as 为文件对象命名为 m1
  • 可以通过 m1.xxx 的方式,访问到文件对象的所有对外接口
function sayHello() {
  console.log("module - 1 : sayHello函数");
}

let people = {
  hair: "color",
};

let firstName = "Michael";

let lastName = "Jackson";

let year = 1958;

export { sayHello, people, firstName };

export default {
  name: "default",
};
  • 在 main.js 中引入整个文件对象: 
import * as m1 from "./moude1.js";

console.log(m1);

  • export default 的作用:是给文件对象添加一个 default 属性
  • default 属性的值也是一个对象,且和 export default 导出的内容完全一致

2.2 导入部分接口

import { sayHello, people } from "./moude1.js";

console.log(sayHello);
console.log(people);


2.3 import 解决命名冲突的问题

  • 如果导入的多个文件中,变量名字相同(产生命名冲突)可以使用 as 进行重命名
import { sayHello as moude1Sayhello, people } from "./moude1.js";

console.log(moude1Sayhello);
console.log(people);


2.4 import 命令的特点

2.4.1 只读属性

  • import 导入的变量为常量,所以不允许修改;
  • 对于引用类型的变量,变量名不指向数据,而是指向数据所在的地址;故可以修改引用类型的属性的值;
  • 常量只是保证变量名指向的地址不变,并不保证该地址的数据不变;
import { a } from "./xxx.js";
a = {}; // error

import { a } from "./xxx.js";
a.foo = "hello"; // a = { foo : 'hello' }

2.4.2 单例模式

  • 多次重复执行同一句 import 语句,那么只会执行一次,而不会执行多次
import { a } from "./xxx.js";
import { b } from "./xxx.js";

// 相当于 import { a, b } from "./xxx.js";

2.4.3 静态执行特性

  • import 是静态执行,所以不能使用表达式和变量
import { "f" + "oo" } from "methods"; // error 内部不接受表达式

let module = "methods3";
import { foo } from module; // error 被弄成变量了

if (true) {
  import { foo } from "method1"; // error 在表达式内不执行
}

2.5 导入默认接口 default

  • export default 本质就是一个叫做 default 的变量/方法,系统允许你为它取任意名字(不包括 default)
// 不需要加{}, 使用任意变量接收
import d from "./moude1.js";
// 等价为 import {default as d} from "./moude1.js"

console.log(d);


2.6 动态导入

  • 按需导入的错误示例:
if (true) {
  import { foo } from "method1";
} else {
  import { foo } from "method2";
}
// error
  • 引擎处理 import 语句是在 编译时进行,此时不会对 if 语句进行分析,因此会报语法错误
  • ES2020 引入 import() 语句,支持动态引入模块

  • import() 函数,接受一个参数 specifier,指定所要加载的模块的位置
  • import() 函数,返回 promise 对象;then 中回调的 data,是文件模块的整个文件对象(包括 export 和 export default)
import(specifier);

// then 中回调的 data 就是文件模块的整个文件对象
// 包括 export 和 export default
import("./moude1.js").then((data) => {
  console.log(data);
});


  • 注意事项:
  1. 不仅是模块,非模块的脚本也可以使用 import()
  2. import() 是运行时执行,也就是说,什么时候运行到这一句,就会加载指定的模块
  3. import() 类似于 Node 的  require() 方法,区别:import() 是异步加载,require() 是同步加载

2.7 动态模块的应用

2.7.1 按需加载

  • 何谓按需加载?在需要的时候,再加载某个模块
  • 举个栗子:实现 当点击按钮时,加载某个模块:
button.addEventListener("click", (event) => {
  import("./dialogBox.js")
    .then((dialogBox) => {
      dialogBox.open();
    })
    .catch((error) => {
      /* Error handling */
    });
});

2.7.2 条件加载

  • import() 可以放在条件语句里,根据不同条件,决定是否加载
if (condition) {
  import('moduleA').then(...);
} else {
  import('moduleB').then(...);
}

2.7.3 动态模块路径

  • import() 允许 动态生成 模块路径
  • 举个栗子:根据 fn() 函数执行结果不同,动态加载不同的模块
import(fn()).then(...);

2.8 import 注意事项

  • 可以通过解构,获得模块的部分 export接口,例如:
  • import("./moude1.js").then(({ sayHello, people }) => { ... });

  • 如果模块导出有 default,可通过参数直接获得
  • import("./moude1.js").then((myModule) => { console.log(myModule.default); });
  • 上面的代码,还可以通过 具名输入 的形式写
  • mport("./myModule.js").then(({ default: theDefault }) => { console.log(theDefault); });

  • 如果想 同时加载多个模块,可以这么写:
Promise.all([
  import('./module1.js'),
  import('./module2.js'),
  import('./module3.js'),
])
.then(([module1, module2, module3]) => {
   ···
});

  • 在 async() 函数中,也可以使用 import()
async function main() {
  const myModule = await import("./myModule.js");
  const { export1, export2 } = await import("./myModule.js");
  const [module1, module2, module3] = await Promise.all([
    import("./module1.js"),
    import("./module2.js"),
    import("./module3.js"),
  ]);
}
main();

3. export import 复合使用

3.1 复合使用时的基本语法

  • 一个模块之中,先输入后输出同一个模块,import() 可以与 export() 写在一起
  • 注意:写成一行后,foo 和 bar实际上并没有被导入当前模块,只是 对外转发 了这两个接口;而当前模块不能直接使用 foo 和 bar
export { foo, bar } from "my_module";

// 可以简单理解为
import { foo, bar } from "my_module";
export { foo, bar };

======================================================

// 接口改名
export { foo as myFoo } from "my_module";

======================================================

// 整体输出
export * from "my_module"

======================================================

// 默认接口
export { default } from "./someModule";

======================================================

// 具名接口 改为 默认接口
export { es6 as default } from './someModule';

// 等同于
import { es6 } from './someModule';
export default es6;

======================================================

// 默认接口 改为 具名接口
export { default as es6 } from "./someModule";

======================================================

// ES2020 之前,有一种import语句,没有对应的复合写法
export * as someIdentifier from "./someModule";

// 等同于
import * as someIdentifier from "./someModule";
export { someIdentifier };

3.2 一些栗子

  • 模块1(module1.js)
let people = {
  hair: "red",
};

let address = "china";

var foo = "bar";
setTimeout(() => (foo = "baz"), 500);

export function sayHello() {
  console.log("module - 1 : sayHello函数");
}

export { people, address, foo as fooDelayedTest };

export default {
  name: "default",
};

  • 模块2 (module2.js)
let address = "Japan";

export { address };

export default {
  name: "default2",
  init: function init(params) {
    console.log(init);
  },
  baseInfo: {
    number: 0,
    length: 10,
  },
};
  • 主引用 (main.js)
// 导入整个文件对象
import * as m1 from "./moude1.js";
// 导入部分接口
import { sayHello, address } from "./moude1.js";
// 导入export中用as重命名后的接口
import { fooDelayedTest } from "./moude1.js";
// 导入address后重命名为peopleAddress
import { address as japanAddress } from "./moude2.js";
// 导入moude1.js中的默认接口
import def from "./moude1.js";
// 导入moude2.js中的默认接口
import def2 from "./moude2.js";

// 导出的默认接口可以被解构
let { name, init, baseInfo } = def2; 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lyrelion

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值