Require/exports与import/export
前言
项目里头需要将一个对话框封装成一个公共的组件Component A(包含一个tree树形控件和一个table),不同类型的页面page1 page2 page3...都需要引入这个Component A,并传入相应的数据。传入的数据会驱动tree与table的创建,而这个tree的节点结构是不同的,table的表头也是不同的。
所以我需要为不同类型的页面创建一个配置文件page1.config.js,在配置文件中定义好tree的结构与table表头。在组件中Component A,根据页面类型动态引入配置文件,创建相应的tree与table。
所以这个时候import ... from不在适用。
解决方案:
(1)在Component A中使用基于page传过来的文件类型,条件引入。采用import();
(2)在page中引入Component A之后,使用import…from导入对应的配置文件,再通过prop传给Component A.
知识点
CommonJS
- 通过require引入基础数据类型时,属于复制该变量。
- 通过require引入复杂数据类型时,数据浅拷贝该对象。
- 出现模块之间的循环引用时,会输出已经执行的模块,而未执行的模块不输出(比较复杂)
- CommonJS模块默认export的是一个对象,即使导出的是基础数据类型
ES6模块
- 不管是基础(复杂)数据类型,都只是对该变量的动态只读引用。动态在于一个模块中变量的变化会影响到另一个模块;只读在于从某个模块引入一个变量时,不允许修改该变量的值。对于复杂数据类型,可以添加属性和方法,但是不允许指向另一个内存空间。
- 针对第一点,可以给出实例。在改变变量时会报错。
vue 动态加载
import命令会被 JavaScript 引擎静态分析,先于模块内的其他模块执行,import和export命令只能在模块的顶层,不能在代码块之中。无法条件引入,无法动态加载。
if (flag == true){
import ABC from './ABC'
} //Error
解决方案
(1)require加载
因为require是运行时加载模块,import命令无法取代require的动态加载功能。若想在代码中动态加载依赖,可以通过引入变量,完成动态加载。
let path = './folder/'+pathName
require(path);
(2)import函数👍👍
import能接受什么参数,import()就能传什么参数。注意的是ES6 import()
返回一个 Promise 对象,是异步加载,而require是同步加载。
特别的,import()也无法使用完全动态的参数,比如import(foo),这里foo可能指代任意的一个路径。import()必须至少包含一个限定的文件目录,如import(./locale/${language}.json)
webpack
let pathName='ABC'
//条件引入,动态加载
if(condition){
import('./path1/'+pathName).then(({module1Name})=>{
let module1Name = module1Name;//配合解构赋值,拿出特定的模块
...//do something
})
} else {
import('./path2'+pathName).then(...)
}
//用在async函数中
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()