如何有条件地导入 ES6 module?

IT技术 javascript module ecmascript-6
2021-01-26 16:46:25

我需要做类似的事情:

if (condition) {
    import something from 'something';
}
// ...
if (something) {
    something.doStuff();
}

上面的代码不能编译;它抛出SyntaxError: ... 'import' and 'export' may only appear at the top level

我尝试使用System.import如图所示here,但我不知道System从哪里来。它是一个最终没有被接受的 ES6 提案吗?那篇文章中指向“编程 API”的链接将我转储到已弃用的文档页面

6个回答

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

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

if (condition) {
    import('something')
    .then((something) => {
       console.log(something.something);
    });
}

这基本上返回了一个Promise。Promise的决议有望有module。该提案还具有其他功能,例如多个动态导入、默认导入、js 文件导入等。您可以在此处找到有关动态导入的更多信息

或者,如果您刚刚命名了导出,您可以解构: if (condition) { import('something') .then(({ somethingExported }) => { console.log(somethingExported); }); }
2021-03-12 16:46:25
最后,一个真正的 ES6 答案!谢谢@thecodejack。根据现在的那篇文章,实际上在撰写本文时处于第 3 阶段。
2021-03-18 16:46:25
在 Firefox 上运行时,npm run build我仍然收到错误消息:SyntaxError: ... 'import' and 'export' may only appear at the top level
2021-04-02 16:46:25
@stackjlei:这个特性还不是 JavaScript 标准的一部分,它只是第 3 阶段的提案!但是它已经在许多较新的浏览器中实现,请参阅caniuse.com/#feat=es6-module-dynamic-import
2021-04-04 16:46:25
该条件动态导入函数不具有仅导入“从 Y 导入 X”具有的特定元素的细粒度能力。事实上,细粒度能力在动态加载中可能更重要(与预处理捆绑相反)
2021-04-11 16:46:25

如果您愿意,可以使用 require。这是一种使用条件 require 语句的方法。

let something = null;
let other = null;

if (condition) {
    something = require('something');
    other = require('something').other;
}
if (something && other) {
    something.doStuff();
    other.doOtherStuff();
}
在这种情况下,吊装有什么影响吗?我遇到了一些问题,如果没有记错的话,提升意味着我在遵循与此接近的模式时意外地导入了一个库。
2021-03-15 16:46:25
2020 年编辑:静态和动态导入现在都是标准 JS 产品的一部分。
2021-03-19 16:46:25
需要指出的是,require()它不是标准 JavaScript 的一部分——它是 Node.js 中的内置函数,因此仅在该环境中有用。OP 没有给出使用 Node.js 的迹象。
2021-03-28 16:46:25
我认为某些东西和其他变量是使用块作用域的 const 来声明的,所以第二个 if 条件将抛出未定义的东西
2021-04-02 16:46:25
最好使用 let 并在块外声明两个变量,而不是使用 'var' 并完全避免块作用域。
2021-04-06 16:46:25

你不能有条件地导入,但你可以做相反的事情:有条件地导出一些东西。这取决于您的用例,因此这种解决方法可能不适合您。

你可以做:

api.js

import mockAPI from './mockAPI'
import realAPI from './realAPI'

const exportedAPI = shouldUseMock ? mockAPI : realAPI
export default exportedAPI

apiConsumer.js

import API from './api'
...

我用它来模拟 mixpanel 等分析库……因为我目前不能有多个构建或我们的前端。不是最优雅的,但有效。根据环境,我在这里和那里只有一些“如果”,因为在 mixpanel 的情况下,它需要初始化。

我认为这真的很好,因为我想在不同的地方导入。之后您可以删除/评论模拟API
2021-03-18 16:46:25
这个解决方案会导致加载不需要的module,所以我认为不是最佳解决方案。
2021-03-25 16:46:25
正如答案中所述,这是一种解决方法。当时,根本没有解决办法。ES6 导入不是动态的,这是设计使然。ES6动态导入函数提案,目前接受的答案中描述的,可以做到。JS 正在发展 :)
2021-04-05 16:46:25

2020 更新

您现在可以将import关键字作为函数(即import()调用以在运行时加载module。

例子:

const mymodule = await import(modulename);

或者:

import(modulename)
    .then(mymodule => /* ... */);

请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports

但是再出口呢?
2021-04-05 16:46:25

看起来答案是,截至目前,你不能。

http://exploringjs.com/es6/ch_modules.html#sec_module-loader-api

我认为目的是尽可能地启用静态分析,而有条件地导入的module打破了这一点。另外值得一提的是——我正在使用Babel,我猜SystemBabel 不支持它,因为module加载器 API 没有成为 ES6 标准。

2020 年编辑:静态和动态导入现在都是标准 JS 产品的一部分。
2021-03-30 16:46:25