1、概述
始终以来开发 vue 我的项目,对 export 和 import 的用法都比拟含糊,看他人怎么写我就照葫芦画瓢,不报错或者性能实现就行,齐全不懂其中的原理,今日闲下来了,就揭穿它们的真面目吧!
历史上,JavaScript 是没有模块的概念的,就像它没有类的概念一样,就连 css 都有 @import,所以社区制订了 CommonJS 和 AMD 标准实现模块加载。为此 ES6 新增了 export 和 import 命令实现了模块性能,而且它的实现形式简略得不堪设想,齐全取代了 CommonJS 和 AMD,现已成为浏览器和服务器通用的模块解决方案。
ES6 的模块设计思维是动态化的,它在编译时确定模块的依赖关系以及输出和输入的变量,也就是说它在编译时就实现了模块加载,咱们称为‘编译时加载’或者动态加载,效率上天然比 CommonJS 要高得多。模块性能次要由两个命令形成:export 和 import。
- export命令规定模块的对外接口
- import命令输出其余模块提供的性能
2、export
一个模块是一个独立的文件,该文件外部的所有变量,内部无奈获取,如果心愿内部可能读取模块外部的某个变量,就必须应用 export 关键字输入该变量。所以咱们通常在 vue 我的项目中引入第三方 js 文件(比方粒子动画)时,往往须要改变此文件,并将最终的变量或者函数或者类裸露进去能力在 vue 文件中通过 import 引入。
export 能够输入变量、函数和类。
// export.js
// bad
export const name = '飘摇的浅樱';
export const age = 17;
export const gender = '女';
export function foo() {console.log('函数 foo');
}
export class Person {constructor(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
getInfo() {return ` 姓名:${this.name}, 性别:${this.gender}, 年龄:${this.age}`;
}
}
// good
const name = '飘摇的浅樱';
const age = 17;
const gender = '女';
function foo() {console.log('函数 foo');
}
class Person {constructor(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
getInfo() {return ` 姓名:${this.name},性别:${this.gender},年龄:${this.age}`;
}
}
export {
name,
age,
gender,
foo,
Person
};
下面两种写法是等价的,然而优先举荐应用上面的写法,因为在文件开端你能一眼就看清楚输入了哪些变量。
export 输入的变量能够应用 as 关键字重命名。
// export.js
const arr = ['html', 'css', 'js']
export {arr as technologies}
// import.js
import {technologies} from './export.js';
export 命令规定的是对外的接口,因而必须与模块外部的变量建设一一对应的关系。
// 谬误写法一
export 10;
// 谬误写法二
var n = 10;
export n;
// 正确写法一
export const n = 10;
// 正确写法二
const n = 10;
export {n};
// 正确写法三
const n = 10;
export {n as m};
正确写法中,import 的时候通过变量 n 或 m 拿到值 10。而在谬误写法中,输入的只有值而没有变量,短少对应关系。
3、import
应用 export 命令定义了对外接口之后,就可能应用 import 命令加载此模块。
// import.js
import {name, age, gender, foo, Person} from './export.js';
console.log(name, age, gender);
foo();
const p = new Person('飘摇的浅樱', 17, '女')
const info = p.getInfo()
console.log(info)
// import.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="import.js" type="module"></script>
</body>
</html>
后果如下:
从例子中能够看出,import 的 {} 内的变量必须与 export 输入的变量名称雷同,否则无奈加载。
import {name1} from './export.js';
import 命令输出的变量都是只读的,因为它的实质是输出接口,所以不容许在加载模块的脚本外面改写接口。
import {obj} from 'export.js';
obj = {}; // Syntax Error : 'obj' is read-only;
4、export default
在第三点中,咱们曾经晓得了,import 的变量必须与 export 输入的变量名称雷同,这个规定导致咱们必须晓得输入的变量名称是什么能力顺利 import,这就减少了咱们浏览文档的工夫,不利于疾速上手。export default 的呈现就是为了让用户不必晓得模块内定义的变量就能加载模块,它为模块指定了默认输入。
// export.js
const tellYourName = (name) => name
export default tellYourName;
// import.js
import tellName from './export.js'
const name1 = tellName('飘摇的浅樱')
console.log(name1) // 飘摇的浅樱
能够看到 import 前面的 tellName 没有加花括号{},并且名称和 export.js 中输入的变量名称不同,这样咱们在援用第三方模块时就无需通晓外部 export 的变量名称是什么。
export default 命令在一个模块中只能应用一次。
5、import()
import 命令做不到 node 的 require 的动静加载性能,因而 ES2020 提案引入 import()函数,反对动静加载模块。
import(spec)
参数 spec 代表加载的模块的地位,import 命令能承受什么参数 import()函数就能承受什么参数,区别只是后者是动静加载。
我所接触到的 import()的利用最常见的就是路由懒加载了。因为当打包构建利用时,JavaScript 包会变得十分大,影响页面加载。这时候咱们将不同路由对应的组件宰割成不同的代码块,而后当路由被拜访的时候才加载对应组件。写法如下:
// index.js
{
path: 'home',
component: () => import('@/views/page/home'),
name: 'home',
meta: {title: '首页'},
}
下面例子中,是再相熟不过的路由文件了,它代表的就是当拜访 home 这个路由时,才加载 home 组件,其余路由均应用此办法,就能大大减小 js 包体积,放慢页面加载速度。
import()函数能够用在任何中央;
import()函数与所加载的模块没有任何动态连贯关系;
import()函数相似于 Node 的 require 办法,但它是异步加载。
6、要害知识点总结
(1)ES6 新增 export 和 import 两个命令实现模块加载;
(2)ES6 模块主动采纳严格模式,而不论你有没有在模块头部加上 ’use strict;’;
(3)export 命令能够输入变量、函数和类;
(4)export 输入的变量就是原本的名字,然而能够应用 as 关键字重命名,援用的时候就是重命名的那个名称;
(5)export 命令规定的是对外的接口,因而必须与模块外部的变量、函数或类倡议一一对应关系;
(6)export 命令输入的接口与其对应的值是动静绑定关系,意思是通过此接口能够获取模块外部实时的值;
(7)import 和 export 命令只能在模块的顶层,不能在代码块之中(比方在函数或者 if 语句之中);
(8)import()函数在路由懒加载、条件加载中最能体现价值;
(9)比拟一下 import 各个写法的含意:import '@/style/index.scss';
执行所加载的模块,然而不输出任何值
import HelloWorld from "@/components/HelloWorld.vue";
援用组件(export default)
import Vue from 'vue';
援用 Vue 模块(export default)
import {uploadOss as alias} from '@/utils/upload';
援用 uploadOss 并重命名为 alias(export)
import {queryList, addUser} from '@/api/home.js';
援用 home.js 中的变量或函数或类(export)
import * as alias from 'vue-router';
加载整个模块(export),alias.xxx
import _, {each, forEach} from 'lodash';
引入默认办法和其余接口
参考地址:https://es6.ruanyifeng.com/#d…