ES6:条件和动态导入语句

Eni*_*jar 71 javascript ecmascript-6

条件

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

if (foo === bar) {
    import Baz from './Baz';
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试了上述但在编译时得到以下错误(来自Babel).

'import' and 'export' may only appear at the top level
Run Code Online (Sandbox Code Playgroud)

动态

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

for (let foo in bar) {
    if (bar.hasOwnProperty(foo)) {
        import Baz from `./${foo}`;
    }
}
Run Code Online (Sandbox Code Playgroud)

以上在编译时从Babel收到相同的错误.

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

推理

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

如果这是不可能的,那么有更好的方法来处理ES6中的大量导入吗?

the*_*ack 41

我们现在有ECMA的动态进口提案.这是在第2阶段.这也可以作为babel预设.

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

if (foo === bar) {
    import('./Baz')
    .then((Baz) => {
       console.log(Baz.Baz);
    });
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这个.动态导入是最佳选择.它们就像require()一样工作,除了它们给你一个承诺而不是一个模块. (2认同)

Jon*_*las 24

您无法动态解析依赖关系,就像imports静态分析一样.但是,您可以require在这里使用一些,例如:

for (let foo in bar) {
    if (bar.hasOwnProperty(foo)) {
        const Baz = require(foo).Baz;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @zerkms - 我认为他们的意思是`import`语句对于静态分析来说是_suitable_ - 因为它们从不是有条件的,工具可以更容易地分析依赖树. (12认同)
  • "因为进口是用于静态分析的."---这句话含糊不清.`import`s旨在导入,而不是用于分析. (8认同)
  • 很难理解"foo""baz"和"bar" - 现实生活中的例子怎么样? (3认同)

Lee*_*Gee 10

由于这个问题被谷歌高度评价,值得指出的是,自从旧的答案发布以来,情况已经发生了变化。

MDN 在Dynamic Imports下有这个条目:

import 关键字可以作为函数调用来动态导入模块。以这种方式使用时,它会返回一个承诺。

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');
Run Code Online (Sandbox Code Playgroud)

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


Eri*_*lli 6

自 2016 年以来,JavaScript 世界已经过去了很多,所以我相信是时候提供关于这个主题的最新信息了。目前动态进口是一个现实在节点浏览器上(本地,如果你不关心IE浏览器,或@巴贝尔/插件语法动态导入,如果你做护理)。

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

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

我们可以使用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
  })
}
Run Code Online (Sandbox Code Playgroud)

但由于返回的是 a Promiseasync/await语法糖也是可能的:

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

现在想想对象解构赋值的可能性!例如,我们可以轻松地将这些命名导出中的一个放在内存中以供后用:

const { bye } = await import('./something.js')
bye('Erick')
Run Code Online (Sandbox Code Playgroud)

或者也许获取这些命名导出之一并将其重命名为我们想要的任何其他内容:

const { hi: hello } = await import('./something.js')
hello('Erick')
Run Code Online (Sandbox Code Playgroud)

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

const { default: helloWorld } = await import('./something.js')
helloWorld()
Run Code Online (Sandbox Code Playgroud)

最后(但并非最不重要)注意: import()可能看起来像一个函数调用,但它不是Function. 这是一种恰好使用括号的特殊语法(类似于 发生的情况super())。所以不可能分配import给变量或使用Function原型的东西,比如call/ apply