您现在的位置是:首页 >学无止境 >commonJs 与 Es6Module 模块化规范网站首页学无止境
commonJs 与 Es6Module 模块化规范
一、commonJs模块化规范
【1.js文件直接输出结果;2.须在node 环境使用,html不认识require,报错Uncaught ReferenceError: require is not defined】
目录结构:
--index.js【入口js,该js文件使用“require 关键字”引入 小模块nodeOut.js】
--nodeOut.js【小模块,该js文件使用“exports 关键字”暴露 数据】
》》nodeOut.js 暴露 数据:
注意:(若引入的是没有 通过exports暴露的 模块(js文件),会得到一个空对象 {} )
1.被引入模块的(js文件,例如nodeOut.js)中,通过exports暴露的是 至少包含一个 键值对 的 对象;被引入模块的(json文件)中,通过exports暴露的是“json文件中的内容”。
将要引入 模块的(js文件)中,通过require('.js')引入的是 至少包含一个 键值对 的 对象。
示例:暴露(一个数据)
exports.address = '郑州',
或
let address = '郑州';
exports.address = address;//暴露出 只包含一个键值对 的对象 {address:"郑州"}
两种方式都一样,通过require('./nodeOut.js')引入,
let a = require('./nodeOut.js');
console.log(a);// {address:"郑州"}
2. 示例:暴露(多个数据)
let names = '张三';
function logout(){
console.log('退出');
}
方式1:(直接导出 1个对象!其中 每个键值对的 键、值 名相同,可简写一个名字)
module.exports = {
names:names, logout
}
方式2:
exports.names = names;
function暴露方式1:exports.logout = logout;
或者 不在上面声明 具名函数,而直接 暴露 出:【如下方式 单独暴露 函数,导出的是 匿名 函数体】
function暴露方式2:exports.logout = function () {
console.log('退出');
};
》》index.js 引入数据:
let a = require('./nodeOut.js');
console.log(a);
通过function暴露方式1 输出: { names: '张三', logout: [Function:logout] },
通过function暴露方式2 输出: { names: '张三', logout: [Function] }
a.logout();// 退出
【补充:json文件只有 2种 数据格式:"string",,,,[{"string"}] 或 [{"string":"string"}]】
3.引入模块时,通过require('./a'),可省略 拓展名,具体有3种情况:
将要引入 模块的 index.js文件 所在目录中,
若同时有a.js、a.json、(文件夹)a/index.js,通过require('./a')引入的 默认是 a.js;
目录结构:
--a/index.js
--a.json
--a.js
--index.js
若同时有a.json、(文件夹)a/index.js,没有a.js,则通过require('./a')引入的 默认是 a.json;
目录结构:
--a/index.js
--a.json
--index.js
若只有 (文件夹)a/index.js,则通过require('./a')引入的 默认是 同目录a文件夹下的 index.js;
目录结构:
--a/index.js
--index.js
let a = require('./a');
console.log(a);
----------------------------------------------------------------------------------------------
二、es6提出的ESmodule模块化规范
【1.html通过<script src:"js文件" type:"module"></script>引入js文件后,html页面输出结果;2.浏览器客户端中使用】
【补充:
---同源策略:页面之间的数据传输的基础是同源(协议、域名、端口号 都相同),否则会出现“跨域”错误;
---不同于 commonJs中的require('a'),函数import('.js')中的“拓展名”,不能省略!只能import('a.js')
---不同于 commonJs中的 exports.key名 = value值、module.exports = {key:value},前面暴露的是个对象;ESmodule中export let 变量名、 export{ 变量名1,函数名1} 暴露的是 变量名(或函数名)
】
目录结构:
--index.html【主页面,该文件以<script src="./main.js" type="module"></script>方式引入, 并执行main.js。[script标签可以跨域请求资源]】
--main.js【入口js,该js文件使用“import {变量名} from '路径' ”引入 大模块tool.js】
--tool/tool.js【大模块,该js文件使用“export 关键字”暴露 数据】
--tool/toolA.js【tool.js中的 小模块toolA.js,该js文件使用“export 关键字”暴露 数据】
--tool/toolB.js【tool.js中的 小模块toolB.js,该js文件使用“export 关键字”暴露 数据】
》》小模块toolA.js 暴露数据:
方式1(分别 暴露 变量名(或函数名)):
export var name = '张三';
export function fn(){
console.log('这里是 toolA.js');
}
方式2(等同于 方式1,将需要暴露的 变量名(或函数名) 都放入 export{ } 中一起暴露出去):
var name = '张三'
function fn(){
console.log('这里是 toolA.js');
}
export{
name,fn
}
方式3,可将 需要暴露的数据放入 obj 对象中,default 暴露obj。那么,在 大模块tool.js中 则不需要 import {变量名1,函数名1...} 引入,而是直接 import obj 引入。
var name = '张三'
function fn(){
console.log('这里是 toolA.js');
}
let obj = {
name: name,
fn: fn
}
export default obj;// 【默认导出obj对象,注意有 default 关键字】
这样做对 后续演示 影响较大,这里直接展示 大模块tool.js更改后的代码:
import obj from './toolA.js'
console.log(obj);// {name: '张三', fn: ƒ}
obj.fn();// "这里是 toolA.js"
》》小模块toolB.js 暴露数据(方式 同理toolA.js):
export function gn(){
console.log('这里是 toolB.js');
}
export var age= 18;
》》大模块tool.js 引入、暴露数据:
方式1:
// 导入【注意:{}中是 变量名(或函数名) 的 集合,整体 非对象】
import {fn,name} from './toolA.js'
import {gn,age} from './toolB.js'
// 导出【注意:{}中是 变量名(或函数名) 的 集合,整体 非对象】
export {
fn,name,gn,age
}
可简写为,方式2(引入 每个 小模块 暴露出的所有数据、并直接 暴露,tool.js作用是数据中转。)
export * from './toolA.js'
export * from './toolB.js'
》》入口文件main.js 引入数据:
方式1:
import {name ,age , fn, gn} from './tools/tool.js';//导入的变量名不能更改!必须与 大模块tool.js暴露出的 变量名(或函数名) 对应。
console.log(name);// 张三
fn();// "这里是 toolA.js"
这里可为 "大模块tool.js暴露出的变量名(或函数名)" 取 别名a,b,f,g,在main中直接使用 别名(之后该别名 默认为 常量,不能被重新赋值)
import {name as a,age as b,fn as f,,gn as g} from './tools/tool.js'
// a = 'zhang'; // 别名a是常量,不能被赋值!
console.log(a);// 张三
【注意:通过 "import {变量名} from '路径' ”引入,该语句只能写在 js文件 最上面,而不能 写在 执行语句 中。如若要按需引入,可以通过 变量 接收 import()的返回值(它是个promise对象)】
示例:
// 需求:当你flag是true的时候 导入a.js 当你flag是false的时候 导入b.js
async function fn() {
var flag = true;
var res;
if (flag) {
// import 'obj1' from './a.js'; // 导入语句只能写在最上面
res = import('./a.js');
console.log(res);// import()函数 导入的是一个promise对象
res.then(value => {
console.log(value.default);// 当a.js中数据暴露方式 是export default obj时,value会添加一个default属性,其值是obj
console.log(value);// 当a.js中数据暴露方式 不是export default obj时,a.js暴露出几个变量(或函数) ,value就会添加几个属性,属性名 与a.js暴露的 变量名(或函数名) 一致。
})
}
}
fn();