我需要做一些类似的事情:

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

上面的代码不能编译;它抛出SyntaxError:…“import”和“export”只能出现在顶层。

我尝试使用系统。导入如下所示,但我不知道系统来自哪里。是ES6提案最终没有被接受吗?那篇文章中的“程序化API”链接把我扔到了一个废弃的文档页面。


当前回答

我可以使用立即调用的函数和require语句来实现这一点。

const something = (() => (
  condition ? require('something') : null
))();

if(something) {
  something.doStuff();
}

其他回答

我知道这不是问题所要求的,但下面是我在使用vite时使用模拟的方法。我相信我们也可以在webpack和其他产品上做到这一点。

假设我们有两个具有相同接口的库:link.js和link-mock.js,那么:

在我的vite.config.js中

export default defineConfig(({ command, mode }) => {
    
    const cfg = {/* ... */}

    if (process.env.VITE_MOCK == 1) {
        cfg.resolve.alias["./link"] = "./link-mock"; // magic is here!
    }

    return cfg;
}

代码:

import { link } from "./link";

在控制台,我们称之为:

# to use the real link.js
npm run vite

# to use the mock link-mock.js
VITE_MOCK=1 npm run vite

or

包中。json脚本

{
    ....
    "scripts": {
        "dev": "vite",        
        "dev-mock": "VITE_MOCK=1 vite"
    }
}

看起来答案是,就目前而言,你不能。

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

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

我们现在有ECMA的动态进口建议。这是第三阶段。这也可作为babel预设。

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

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

这基本上返回了一个承诺。决议的承诺是有预期的模块。该建议还具有其他功能,如多个动态导入,默认导入,js文件导入等。您可以在这里找到关于动态导入的更多信息。

2020年更新

你现在可以调用import关键字作为函数(即import())在运行时加载一个模块。它返回一个Promise,解析为带有模块导出的对象。

例子:

const mymodule = await import('modulename');
const foo = mymodule.default; // Default export
const bar = mymodule.bar; // Named export

or:

import('modulename')
    .then(mymodule => {
        const foo = mymodule.default; // Default export
        const bar = mymodule.bar; // Named export
    });

看到https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import Dynamic_Imports

在JS中有条件地导入和导出

const value = (
    await import(`${condtion ? `./file1.js` : `./file2.js`}`)
).default

export default value