ES6:有条件的&动态导入语句

时间:2016-03-10 11:08:03

标签: javascript ecmascript-6

条件

是否可以使用下面的条件导入语句?

if (foo === bar) {
    import Baz from './Baz';
}

我已尝试过上述内容,但在编译时会收到以下错误(来自Babel)。

'import' and 'export' may only appear at the top level

动态

是否可以使用如下的动态导入语句?

for (let foo in bar) {
    if (bar.hasOwnProperty(foo)) {
        import Baz from `./${foo}`;
    }
}

以上在编译时从Babel收到同样的错误。

这是可能做的还是我缺少的东西?

推理

我试图这样做的原因是我有很多“页面”的导入,它们遵循类似的模式。我想通过动态for循环导入这些文件来清理我的代码库。

如果无法做到这一点,那么有更好的方法来处理ES6中的大量导入吗?

5 个答案:

答案 0 :(得分:32)

我们现在有ECMA的动态导入提案。这是在第2阶段。这也可以babel-preset

以下是根据您的情况进行条件渲染的方法。

if (foo === bar) {
    import('./Baz')
    .then((Baz) => {
       console.log(Baz.Baz);
    });
}

这基本上是一个承诺。承诺的解决方案预计将有模块。该提案还包含多个动态导入,默认导入,js文件导入等。您可以找到有关dynamic imports here的更多信息。

答案 1 :(得分:21)

您无法动态解决依赖关系,因为imports适用于静态分析。但是,你可以在这里使用一些require,例如:

for (let foo in bar) {
    if (bar.hasOwnProperty(foo)) {
        const Baz = require(foo).Baz;
    }
}

答案 2 :(得分:7)

由于这个问题在Google的高度评价中,因此值得一提的是,自从发布了较早的答案以来,情况已经发生了变化。

MDN在Dynamic Imports下有此条目:

可以将import关键字称为动态导入 模块。当以这种方式使用时,它将返回一个promise。

import('/modules/my-module.js')
  .then((module) => {
    // Do something with the module.
  });

// This form also supports the await keyword.
let module = await import('/modules/my-module.js');

有关该主题的有用文章可以在Medium上找到。

答案 3 :(得分:2)

要求无法解决您的问题,因为它是同步通话。有几个选项,它们都涉及

  1. 询问您需要的模块
  2. 等待退回模块的承诺
  3. 在ECMA Script中,支持使用SystemJS的延迟加载模块。当然,并非所有浏览器都支持此功能,因此在此期间您可以使用JSPM或SystemJS垫片。

    https://github.com/ModuleLoader/es6-module-loader

答案 4 :(得分:1)

自2016年以来,JavaScript世界已经过去了很多,所以我认为是时候提供有关此主题的最新信息。当前 Dynamic imports都是现实的 on Nodeon browsers(如果您不关心IE,则自然可以;如果您确实关心IE,则可以@babel/plugin-syntax-dynamic-import) )。

因此,请考虑一个示例模块something.js,该模块具有两个命名的导出和一个默认的导出:

export const hi = (name) => console.log(`Hi, ${name}!`)
export const bye = (name) => console.log(`Bye, ${name}!`)
export default () => console.log('Hello World!')

我们可以使用import()语法轻松,干净地有条件地加载它:

if (somethingIsTrue) {
  import('./something.js').then((module) => {
    // Use the module the way you want, as:
    module.hi('Erick') // Named export
    module.bye('Erick') // Named export
    module.default() // Default export
  })
}

但是由于返回值是Promise,因此async / await语法糖也是可能的:

async imAsyncFunction () {
  if (somethingIsTrue) {
    const module = await import('./something.js')
    module.hi('Erick')
  }
}

现在考虑一下Object Destructuring Assignment带来的可能性!例如,我们能够轻松地将只有一个名为exports的内容存储在内存中以供以后使用:

const { bye } = await import('./something.js')
bye('Erick')

或者获取其中一个名为export的文件并将其重命名为我们想要的其他名称:

const { hi: hello } = await import('./something.js')
hello('Erick')

或者甚至将默认导出的函数重命名为更有意义的东西:

const { default: helloWorld } = await import('./something.js')
helloWorld()

仅是最后(但并非最不重要)的说明: import()看起来像函数调用,但不是Function。这是一种特殊的语法,恰好使用括号(类似于super()的情况)。因此,不可能将import分配给变量或使用Function原型的东西,例如call / apply