ES6-Module语法之export&&import
// 浏览器中使用ES6 Module script的type必须写上module
https://www.jianshu.com/p/e89e9d1d1caa
而对于Chrome浏览器,则会有一点问题。
直接打开html文件时,Chrome浏览器会报错:
Access to script at 'file:///masaike' from origin 'null' has been blocked by CORS policy: The response is invalid.
这并不是Chrome不支持加载模块,而是ES6模块遵循同源策略。解决方法就是打开本地服务器,让各个文件同源就可以了。
// <script type="module">
// import {a} from '../static/module.js';
// console.log(a);
// </script>
// <!-- 或者 -->
// <script src="../static/import.js" type="module"></script>
//形式一
//使用export导出的变量 import后面必须跟{}
//index.html
// <script type="module">
// import {area} from './circle.js';
// console.log(area(1)); //3.141592653589793
// </script>
//circle.js
// export function area(radius){
// return Math.PI * radius * radius;
// }
// export function circle(radius){
// return 2 * Math * PI *radius;
// }
//形式二(export导出变量)
//circle.js
// export var m = 1;
// index.html
// <script type="module">
// import {m} from './circle.js';
// console.log(m);
// </script>
//形式三
// circle.js
// export function area(radius){
// return Math.PI * radius * radius;
// }
// index.html
// import {area as a} from './circle.js';
// console.log(a(1));
// 形式四
// circle.js
// function area(radius){
// return Math.PI * radius * radius;
// }
// export {area as a};
// index.html
// import {a} from './circle.js';
// console.log(a(1));
// 形式五
// circle.js
// function area(radius){
// return Math.PI * radius * radius;
// }
// export {area as a};
// index.html
// import {a as area} from './circle.js';
// console.log(area(1));
// 形式六
//下面的import命令可以用任意名称指向 circle的输出方法,这时就不需要知道模块输出的函数名,
//需要注意的是这时的import命令后面不使用大括号 export default只能使用一次
//circle.js
// export default function () {
// console.log('123');
// }
//index.html
// <script type="module">
// import custom from './circle.js';
// console.log(custom()); //123
// </script>
//一个模块就是一个独立的文件。该文件内部的所有变量外部无法获取 如果希望外部能够读取
// 模块的内部的变量就必须使用exports关键字输出变量。
//方法一
export var firstName = 'pittle';
export var lastName = 'zjy';
export var year = 1999;
//方法二与上面的方法相同 但优先使用方法二(这样就可以在脚本尾部一眼看清楚所有变量)
var firstName = 'pittle';
var lastName = 'zjy';
var year = 1999;
export {firstName,lastName,year};
// exports除了能输出变量还能输出函数
exports function multiply(x,y){
return x*y;
}
// 上面代码输出一个函数
// 正常情况下export输出的变量就是本来的名字,但是可以使用as关键字重命名
function v1(){}
function v2(){}
export {
v1 as funv1,
v2 as funv2,
v2 as funv22
}
// 上面代码as关键字重命名了函数v1和v2的对外接口,重命名后v2可以用不同的名字输出两次
//
// 需要特别注意的是,export命令规定的是对外接口 必须与模块内部的变量建立一一对应的关系
export 1; //报错
var m = 1; export m; //报错
//上面的两种写法都会报错,因为没有提供对外的接口,第一种写法直接输出1第二种写法通过变量m
// 依然直接输出1,1只是一个值,不是接口
//正确的写法如下(export输出变量的时候需要{},import导入的时候也需要{})
(1)var m = 1;export {m};
(2)export var m = 1;
(3)var n = 1; export {n as m};
// -------------------------------------------------
注意:export default 对应的import不需要{} export对应的import需要{}
export default指定模块的默认输出,显然一个模块只能有一个默认输出,因此export default命令只能使用一次
// ---------------------------------------------------
export default function crc32(){}; //输出
import crc32 from 'crc32';//输入
export function crc32(){}//输出
import {crc32} from 'crc32' //输入
// 本质上export default就是输出一个叫做default的变量或方法
//然后系统允许我们为它取任何名字
function add(x,y){
return x*y;
}
export {add as default};
//等同于
export default add;
import {default as xxx} from 'module';
// 等同于
import xxx from 'modules';//注意哦:export default导出的变量没有加{}哦
// 正是因为export default命令其实只是输出一个叫做default的变量,所以它后面不能跟
// 变量声明语句
export var a = 1; //正确
var a = 1;
export default a; //正确
export default var a = 1; //错误
// export default a 的含义是将变量a的值赋给变量default
export default 42;//正确 指定对外的接口为default
export 42;//报错 没有指定对外的接口
//有了export default 命令,输入模块就非常直观了,以lodash为例
import _ from 'lodash';//将lodash库导入为_就好像import $ from 'JQuery'
//如果想一条import 语句中同时输入默认方法和其他接口,可以写成下面这样
import _,{each,each as forEach} from 'lodash';//each as forEach表示将each重命名为forEach
// export default 也可以用来输出一个类
// Myclass.js
export default class{}
// main.js
import Myclass from "Myclass";
let o = new Myclass
//条件是:如果在一个模块之中(注意是一个模块比如lodash) 输入后输出同一个模块,那import和export可以写一起
// export 与 import 的复合用法
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';
作为中转模块导出
有时候为了避免上层模块导入太多的模块,我们可能使用底层模块作为中转,直接导出另一个模块的内容如下:
- //------ myFunc.js ------
- export default function() {...};
- //------ lib.js ------
- export * from 'myFunc';
- export function each() {...};
- //------ main.js ------
- import myFunc,{ each } from 'lib';
这样main.js只需导入lib模块即可,虽然myFunc模块从lib模块导出,但是lib却不能使用myFunc模块的内容。
// 具名接口改默认接口写法
export {es6 as default} from './someModule';
//等同于
import {es6} from './someModule';
export default es6;
//默认接口改具名接口写法
export {default as es6} from './someModule'
//下面的3中import 语句没有复合写法
import * as someId from 'someModule';
import someId from 'someModule';
import someId,{namedId} from 'someModule';
//为了做到形式对称有一个提案 详情请看es6基础入门Page469
// 跨模块常量
// const 声明的常量只在当前代码块内有效.如果想设置跨模块的常量(跨多个文件);或者说一个值被多个模块共享,可以
// 采用下面的方法
//circle.js
export const A = 1;
export const B = 3;
export const C = 4;
//index.html
// <script type="module">
// import * as cons from './circle.js';
// console.log(cons.A); // 1
// </script>
//如果常量特别多可以建立一个专门的constant目录,将各种常量写在不同的文件里面并保存在该目录下
//constants/db.js
export const db = {
url:'http://www.baidu.com',
admin_user:'admin',
admin_pass:'pass'
}
// constants/user.js
export const users = ['root','admin','staff','ceo'];
//然后将这些文件输出的常量合并在index.js里面
//consants/index.js
export {db} from './db';
export {users} from './users';
//最后使用的时候只需要加载index.js就可以了
//script.js
import {db,users} from './constants'//./constants相当于./constants/index
// import()还有可以是个函数呀,千万别搞混了哟
// ES6 import命令加载模块为编译时加载 require是运行时加载
// 编译时的加载效率高于运行时的加载效率
// 但import语句无法在运行时加载模块
// import()函数出世 可以用在任何地方 不仅仅是模块 非模块的脚本也可以使用
// 它是运行时执行,也就是说运行到这一句便会加载指定模块
// 腻歪import()函数与所加载的模块没有静态连接关系 这一点也与import语句不相同
// 关键字import可以像调用函数一样来动态的导入模块。以这种方式调用,将返回一个 promise。
import('/modules/my-module.js')
.then((module) => {
// Do something with the module.
});
// 这种使用方式也支持 await 关键字。
let module = await import('/modules/my-module.js');