node.js中的ES6变量导入名称?

Vyt*_*kus 101 javascript node.js ecmascript-6

是否可以在使用ES6导入时将某些内容导入到提供变量名称的模块中?

即我想在运行时导入一些模块,具体取决于配置中提供的值:

import something from './utils/' + variableName;
Run Code Online (Sandbox Code Playgroud)

Fel*_*ing 61

不是import声明.import并且export以这样的方式定义它们是静态可分析的,因此它们不能依赖于运行时信息.

您正在寻找加载器API(polyfill),但我对规范的状态有点不清楚:

System.import('./utils/' + variableName).then(function(m) {
  console.log(m);
});
Run Code Online (Sandbox Code Playgroud)

  • 我需要"需要"系统吗?它不是在全球范围内.. Ps我正在使用babel js (3认同)
  • 这还是个问题吗?我需要动态加载ES6模块,但我没有成功.. (3认同)
  • 虽然这是 2015 年最好的答案,但 [dynamic `import()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports) 在 ES2020 中得到了标准化并且受 Node.js 和所有现代浏览器支持,请参阅[此答案](/sf/answers/3369360501/)。 (3认同)

aps*_*ers 26

除了Felix的回答之外,我还会明确指出ECMAScript 6语法目前不允许这样做:

ImportDeclaration :

  • import ImportClause FromClause;

  • import ModuleSpecifier;

FromClause :

  • 来自 ModuleSpecifier

ModuleSpecifier :

  • 字符串字面量

ModuleSpecifier只能是一个串文字,而不是任何其他种类等的表达的AdditiveExpression.

  • 很遗憾,这并没有扩展到包含`const``字符串文字.它们是静态可分析的,不是吗?这将使重用依赖的位置成为可能.(例如,导入模板并同时提供模板和模板的位置). (2认同)

pti*_*tim 24

虽然这实际上不是动态导入(例如,在我的情况下,我下面导入的所有文件都将由webpack导入和捆绑,而不是在运行时选择),我一直在使用的模式可能在某些情况下有所帮助, :

import Template1 from './Template1.js';
import Template2 from './Template2.js';

const templates = {
  Template1,
  Template2
};

export function getTemplate (name) {
  return templates[name];
}
Run Code Online (Sandbox Code Playgroud)

或者:

// index.js
export { default as Template1 } from './Template1';
export { default as Template2 } from './Template2';


// OtherComponent.js
import * as templates from './index.js'
...
// handy to be able to fall back to a default!
return templates[name] || templates.Template1;
Run Code Online (Sandbox Code Playgroud)

我不认为我可以轻易地回退到默认值require(),如果我尝试导入不存在的构造模板路径,则会抛出错误.

需要和导入之间的良好示例和比较可以在这里找到:http://www.2ality.com/2014/09/es6-modules-final.html

关于从@iainastacio重新导出的优秀文档:http://exploringjs.com/es6/ch_modules.html#sec_all-exporting-styles

我有兴趣听到关于这种方法的反馈:)

  • 我应该想到这一点。很好的解决方案,无论您如何导入内容(即使您没有导入任何内容)。有一个您想要稍后获取其名称或按名称获取的项目列表吗?将它们放在对象文字中而不是数组文字中,并让对象语法根据它们的本地常量/变量名称来命名它们。如果您再次需要它们作为列表,只需执行“Object.values(templates)”即可。 (2认同)

Nic*_*mid 10

有一个新规范称为ES模块的动态导入.基本上,你只是打电话import('./path/file.js'),你的好去.该函数返回一个promise,如果导入成功,它将与模块​​一起解析.

async function import() {
   try {
      const module = await import('./path/module.js');
   } catch (error) {
      console.error('import failed');
   }
}
Run Code Online (Sandbox Code Playgroud)

用例

用例包括React,Vue基于路由的组件导入,以及在运行时需要延迟加载模块的能力.

更多的信息

以下是对Google Developers的解释.

浏览器兼容性

MDN称,目前每一款Chrome浏览器都支持它,而Firefox 66则支持旗帜.


MCT*_*r17 9

我了解importNode.js 中专门针对 ES6 提出的问题,但以下内容可能会帮助其他人寻找更通用的解决方案:

let variableName = "es5.js";
const something = require(`./utils/${variableName}`);
Run Code Online (Sandbox Code Playgroud)

请注意,如果您要导入 ES6 模块并需要访问default导出,则需要使用以下其中一种:

let variableName = "es6.js";

// Assigning
const defaultMethod = require(`./utils/${variableName}`).default;

// Accessing
const something = require(`./utils/${variableName}`);
something.default();
Run Code Online (Sandbox Code Playgroud)

您还可以通过这种方法使用解构,这可能会增加您对其他导入的语法熟悉度:

// Destructuring 
const { someMethod } = require(`./utils/${variableName}`);    
someMethod();
Run Code Online (Sandbox Code Playgroud)

不幸的是,如果您既要访问default又要解构,则需要分多个步骤执行此操作:

// ES6 Syntax
Import defaultMethod, { someMethod } from "const-path.js";

// Destructuring + default assignment
const something = require(`./utils/${variableName}`);

const defaultMethod = something.default;    
const { someMethod, someOtherMethod } = something;
Run Code Online (Sandbox Code Playgroud)


sta*_*rsp 5

我使用时遇到了类似的问题Vue.js:当您在import(variableName)构建时使用变量时,Webpack 不知道在哪里寻找。因此,您必须将其限制为具有适当扩展名的已知路径,如下所示:

let something = import("@/" + variableName + ".js") 
Run Code Online (Sandbox Code Playgroud)

github 上针对同一问题的答案对我非常有帮助