三、ES6中的模块(CMD规范)
重点:在ES6中新增了js文件的暴露和引入的新写法:(import和export)
3.1 import和export基本使用(普通暴露)
之前学习过Nodejs,用require、exports来引入和暴露。
W3C那些老头想:Ryan Dahi那个小孩挺牛逼, 在Nodejs发明了require()和exports挺好用, 我们也制定一个标准吧! 于是研究出了这样的语法:
require() -> import
exports.*** -> export
module.exports -> default
使用export const暴露函数
在yuan.js文件暴露
export const mianji = (r) => 3.14 * r * r;
export const zhouchang = (r) => 2 * 3.14 * r;
在main.js文件接收:import {} from "./路径"; 接收函数。
import {mianji,zhouchang} from "./yuan.js"; //引入
console.log(mianji(10));
console.log(zhouchang(10));
注意两个问题:
暴露时是什么名字, 接收时一定是什么名字, 比如暴露的是mianji, 接收就叫mianji。
路径必须"./"开头
W3C新发明的CMD规范(export和import)关键字, 如今的浏览器和Node平台都不支持。
那现在不支持怎么办?
webpack应运而生, webpack是一个很智能的文件打包器, 你只需告诉它主入口文件是谁, 它就能顺着import链进行打包, 最后能合并成为一个新的js文件, 将不再有import和export的语法。
cnpm install webpack -g
webpack打包命令
webpack main.js all.js
webpack进行了3个事情:
1) 从main.js出发, 顺着import链寻找每一个被引用的js文件
2) 将每一个js文件智能合并打包, 比如一个export暴露的函数没有被使用, 将不会被打包;
3) 去import、export化, 也就是说all.js是IE8都兼容的。
webpack是一个构建工具, 在html中只需要引入all.js一个文件即可
命名空间
比如增加一个fang.js也向外暴露两个函数, 也叫mianji和zhouchang
export const mianji = (a)=> 3.14 * a * a;
export const zhouchang = (a)=> 3.14 * a * 4;
此时主入口文件:
import {mianji,zhouchang} from "./yuan.js";
import {mianji,zhouchang} from "./fang.js";
console.log(mianji(15))
console.log(zhouchang(15))
会报错, 因为函数名重复了:
解决方法就是命名空间:用import * as fang from "./路径"; 来接收函数
import * as yuan from "./yuan.js";
import * as fang from "./fang.js";
console.log(yuan.mianji(10))
console.log(fang.mianji(10))
此时函数必须通过yuan打点, 或fang打点调用, 因为接收到的是一个JSON。
也就是说import * as fang from "./文件";的语法, 可以有效避免函数的名字冲突。
注意:import * as的这个名字, 必须和文件名相同。
默认暴露
如果js文件中是一个类(构造函数), 此时不希望有命名空间, 用默认暴露:
export default
相当于nodejs中的module.exports
比如写一个文件叫People.js这个文件向外暴露一个类:
export default class People {
constructor(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
change(){
alert(`啦啦啦!我是卖报的${this.name},今年${this.age}`)
}
}
在主入口文件, 就不用{}引用这个类:
import People from "./People.js"; //类叫什么名字, import后就叫什么名字
var xiaoming = new People("小明",12,"男");
xiaoming.change();
一个文件可以有多个普通暴露, 但是只能有一个默认暴露
// 默认暴露
export default class People {
constructor(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
change(){
alert(`啦啦啦!我是卖报的${this.name},今年${this.age}`)
}
}
//以下是普通暴露
export const a = 100;
export const b = 200;
export const f1 = function(){
alert("我是普通的暴露函数f1")
};
export const f2 = function(){
alert("我是普通的暴露函数f2")
};
注意:引入时,接收默认的暴露,不能加{},接收普通暴露的加{}
// import People from "./People.js"; //类叫什么名字,import后就叫什么名字
import People, {a,b,f1,f2} from "./People.js";
console.log(a)
console.log(b)
f1();
f2();
var xiaoming = new People("小明",12,"男");
xiaoming.change();
暴露模块:
普通暴露 export const
默认暴露 export default
引用模块:
普通引用 import {mianji,zhouchang} "./yuan.js"
import * as yuan "./yuan.js"
默认引用(类的引用) import People from "./People.js"
默认暴露和普通暴露一起引用 import People,{a,b,f1,f2} from "./People.js";