import()提供了动态加载 ECMAScript 模块的功能
Posted 好程序员
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了import()提供了动态加载 ECMAScript 模块的功能相关的知识,希望对你有一定的参考价值。
Domenic Denicola 向 ECMAScript 提议在第 3 阶段中加入“”。它提供了动态加载 ECMAScript 模块的功能。这篇博文会解释这个功能。
ECMAScript 模块是静态的
ECMAScript 模块是完全静态的:你必须在编译期指定要导入或者导出什么,不能在运行时根据当时的情况修改。这样做会带来一些好处,你可以在 中阅读到相关内容。
静态结构的导入有两种语法。看看下面的示例:
import * as someModule from './dir/someModule.js';
首先,这个导入申明必须放在模块的顶层。这就是说你不能在 if
语句或者事件处理函数中导入模块。
第二,模块说明符'./dir/someModule.js'
是固定的;你不能在运行时候把它计算出来(比如通过函数调用之类的)。
提议引入动态导入模块的功能
关于动态加载模块提议的运算符像下面的代码那样工作:
const moduleSpecifier = './dir/someModule.js';
import(moduleSpecifier)
.then(someModule => someModule.foo());
这个运算符用起来像个函数:
它的参数是一个与
import
申明的模块说明符格式一样字符串。不同的是,这个参数可以通过一个结果为字符串的表达式来提供。这个“函数调用”返回一个 Promise。模块加载完成,则 Promise 完成。
尽管它很像一个函数,import()
是一个运算符:为了能确定想对于当前模块的模块说明符,它需要知道是从哪个模块调用的。普通的函数可没有办法直接找到。
应用场景
按需加载
在 Web 应用刚启动的时候,有些功能不是必须的,它们可以根据后后面的需求来加载。import()
对此很有帮助,因为它可以帮你为模块提供这样的能力。比如:
button.addEventListener('click', event => {
import('./dialogBox.js')
.then(dialogBox => {
dialogBox.open();
})
.catch(error => {
/* Error handling */
})
});
按条件加载模块
有时候你可能想根据某些条件来加载模块。比如,在旧平台上加载 polyfill。代码会像下面这样。
if (isLegacyPlatform()) {
import(···)
.then(···);
}
计算模块描述符
比如在应用需要国际化的时候,它可以帮助你动态计算模块描述符:
import(`messages_${getLocale()}.js`)
.then(···);
提示
通过解构访问导出
解构对于访问模块的导出的很用:
import('./myModule.js')
.then(({export1, export2}) => {
··· });
访问默认导出
对于默认导出,你需要知道 default
是一个关键字。把它作为一个属性,使用点号就可以访问:
import('./myModule.js')
.then(myModule => {
console.log(myModule.default);
});
但是你不能把它当作变量名来用:
import('./myModule.js')
.then(({default: theDefault}) => {
console.log(theDefault);
});
动态加载多个模块
可以通过 Promise.all()
来一次性加载多个模块:
Promise.all([
import('./module1.js'),
import('./module2.js'),
import('./module3.js'),
])
.then(([module1, module2, module3]) => {
··· });
异步函数和 import()
import()
返回 Promise,这意味着你可以通过 (这是 ECMAScript 2017 的内容) 来使用它,让语法更漂亮:
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();
在模块或者脚本的顶层,你会发现使用立即执行的箭头函数非常有用:
(async () => {
const myModule = await import('./myModule.js');
})();
支持 import()
Node.js: Guy Bedford 的 提供了一个 Node.js 的可执行程序来支持 ES6 语法和
import()
。webpack v1: 是一个将
import()
转译为require.ensure()
的 Babel 插件。webpack v2 ( 或更新版本):
长按二维码分享更多精彩
以上是关于import()提供了动态加载 ECMAScript 模块的功能的主要内容,如果未能解决你的问题,请参考以下文章