在做前端开发时,我们使用import引入需要的模块时会发现一个问题,有的需要使用 {}
,有的不需要:
import { AUDIT } from './constants.js'
import tools from '@/utils/tools'
这其实前端ES6的模块命令,初次接触的小白肯定会很疑惑,这里就具体讲一下ES6的模块命令,学习完就能解答上面的问题了。
概述: 在ES6之前的模块加载方案主要有CommonJS 和 AMD 两种。但这两种都只能在运行时加载,无法做到在编译时静态优化。ES6新增了两个模块命令:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
模块
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。
// constants.js
const AUDIT = {
COLUMNS: [
{
title: '操作人员',
dataIndex: 'operator'
},
{
title: '时间',
dataIndex: 'datetime'
},
{
title: '操作类型',
dataIndex: 'operation'
}
]
}
这里constants.js就是一个模块,它的变量AUDIT此时是无法被外部获取使用的。如果你希望外部能够读取constants.js模块中的AUDIT变量,就必须使用export
关键字输出该变量。
export 命令
export
命令显式指定输出的代码
// constants.js
export { AUDIT }
这里用export
命令对外部输出了AUDIT常量。
除了上面那种写法,还有另外一种写法:
// constants.js
export const AUDIT = {
COLUMNS: [
{
title: '操作人员',
dataIndex: 'operator'
},
{
title: '时间',
dataIndex: 'datetime'
},
{
title: '操作类型',
dataIndex: 'operation'
}
]
}
export命令除了输出变量,还可以输出函数或类(class)。
export function multiply (x, y) {
return x * y
}
对外输出一个函数multiply
。
关键字as
的使用:
function v1() { ... }
function v2() { ... }
export {
v1 as streamV1,
v2 as streamV2,
v2 as streamLatestVersion
}
上面代码使用as关键字,重命名了函数v1和v2的对外接口。重命名后,v2可以用不同的名字输出两次。
import 命令
使用export
命令定义了模块的对外接口以后,其他 JS 文件就可以通过import
命令加载这个模块。
import { AUDIT } from './constants.js'
上面的import
命令,用于加载constants.js文件,并从中获取变量。import
命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(constants.js)对外接口的名称相同。
注意:
1、import命令输入的变量都是只读的
,不允许在外部改写。
2、import
后面的from
指定模块文件的位置,可以是相对路径,也可以是绝对路径。如果不带有路径,只是一个模块名,那么必须有配置文件,告诉 JavaScript 引擎该模块的位置。
import { mapActions } from 'vuex'
export default 命令
上面介绍了export
和import
,我们发现使用import
命令的时候,我们必须知道所要使用的模块中的变量名或函数名,否则无法引入。为了解决这个问题,就要用到export default
命令,为模块指定默认输出。
// settings.js
const list = {
url: `/settings/`,
method: 'get'
}
const add = {
url: `/settings/`,
method: 'post'
}
export default {
list,
add
}
引入使用时,不需要使用{}
,而且可以为该变量指定任意名字customName
:
import customName from './settings'
注意:export default
命令用于指定模块的默认输出。显然,一个模块只能有一个默认输出,因此export default
命令只能使用一次。所以,import
命令后面才不用加大括号,因为只可能唯一对应export default
命令。
这里就解释了我们开头遇到的问题,tools
引入不需要大引号:
import tools from '@/utils/tools'
// tools.js
const tools = {
/**
* 判断传入值是否为空
* @param {Any} value 值
*/
isEmpty (value) {
const dataType = checkDataType(value)
let isEmpty
switch (dataType) {
case 'String':
isEmpty = value === ''
break
case 'Array':
isEmpty = !value.length
break
case 'Object':
isEmpty = !Object.keys(value).length
break
default:
isEmpty = false
}
return isEmpty
},
/*
对象数组根据某个key进行排序
*/
compare (key) {
return (a, b) => {
const val1 = a[key]
const val2 = b[key]
return val1 - val2
}
}
}
export default tools
import() 命令
前面说过,import
命令是静态的,固然有利于编译器提高效率,但也导致无法在运行时加载模块,所以它无法做到按需加载
和条件加载
,要想满足这两种场景,我们可以使用import()
函数。
import()
函数相当于NODE中的require
方法,它返回一个Promise对象。
例一:按需加载
button.addEventListener('click', event => {
import('./dialogBox.js')
.then(dialogBox => {
dialogBox.open();
})
.catch(error => {
/* Error handling */
})
});
上面代码中,import()
方法放在click事件的监听函数之中,只有用户点击了按钮,才会加载这个模块。
例二:条件加载
if (condition) {
import('moduleA').then(...);
} else {
import('moduleB').then(...);
}
根据不同的情况,加载不同的模块。
注意:import()
加载模块成功以后,这个模块会作为一个对象,当作then方法的参数.