如何执行“变量”ES6导入
How to perform a “variable” ES6 import?
在使用ES6导入时,是否可以将某些内容导入到提供变量名的模块中?
也就是说,我想在运行时根据配置中提供的值导入一些模块:
import something from './utils/' + variableName;
请注意,我使用的是Node.js,但答案必须考虑与ECMAScript模块的兼容性。
不使用import
语句。import
和export
的定义方式是它们可以静态分析,因此它们不能依赖于运行时信息。
您正在寻找加载程序API(polyfill),但我有点不清楚规范的状态:
System.import('./utils/' + variableName).then(function(m) {
console.log(m);
});
虽然这实际上不是一个动态导入(例如,在我的情况下,我在下面导入的所有文件都将由webpack导入和捆绑,而不是在运行时选择),但我一直在使用的一种模式在某些情况下可能会有所帮助:
import Template1 from './Template1.js';
import Template2 from './Template2.js';
const templates = {
Template1,
Template2
};
export function getTemplate (name) {
return templates[name];
}
或者:
// 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;
我不认为require()
可以很容易地恢复到默认值,如果我试图导入一个不存在的构建模板路径,它会引发错误。
在这里可以找到require和import之间的好例子和比较:http://www.2ality.com/2014/09/es6-modules-final.html
关于从@iainastacio重新导出的优秀文档:http://exploringjs.com/es6/ch_modules.html#sec_all-导出样式
我很想听听关于这种方法的反馈:)
有一个新的规范,称为ES模块的动态导入。基本上,你只要打电话给import('./path/file.js')
就可以了。该函数返回一个promise,如果导入成功,该promise将与模块一起解析。
async function importModule() {
try {
const module = await import('./path/module.js');
} catch (error) {
console.error('import failed');
}
}
用例
用例包括React、Vue等基于路由的组件导入,以及在运行时需要延迟加载模块的能力。
进一步信息
以下是对谷歌开发者的解释。
浏览器兼容性(2020年4月)
根据MDN的数据,目前所有主要浏览器(IE除外)都支持它,caniuse.com在全球市场份额中显示出87%的支持率。同样,IE或非铬Edge不支持。
除了Felix的答案之外,我还要明确指出,ECMAScript 6语法目前不允许这样做:
进口申报 :
import ImportClause FromClause
import ModuleSpecifier
从条款 :
- 来自 模块指定器
模块指定器 :
- 字符串文字
ModuleSpecifier只能是StringLiteral,而不能是任何其他类型的表达式,如AdditiveExpression。
我理解Node.js中专门针对ES6 import
提出的问题,但以下内容可能会帮助其他人寻找更通用的解决方案:
let variableName = "es5.js";
const something = require(`./utils/${variableName}`);
请注意,如果您正在导入ES6模块并需要访问default
导出,则需要使用以下其中一个:
let variableName = "es6.js";
// Assigning
const defaultMethod = require(`./utils/${variableName}`).default;
// Accessing
const something = require(`./utils/${variableName}`);
something.default();
您还可以将析构函数与此方法一起使用,这可能会增加对其他导入的语法熟悉程度:
// Destructuring
const { someMethod } = require(`./utils/${variableName}`);
someMethod();
不幸的是,如果您想访问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;
我在使用Vue.js
时遇到了类似的问题:当您在构建时在import(variableName)
中使用变量时,Webpack不知道该在哪里查找。所以你必须将它限制在已知的路径上,并进行适当的扩展,比如:
let something = import("@/" + variableName + ".js")
github中对同一问题的回答对我很有帮助。
您可以使用非ES6表示法来实现这一点。这就是对我有效的:
let myModule = null;
if (needsToLoadModule) {
myModule = require('my-module').default;
}
我不太喜欢这种语法,但它有效:
而不是写入
import memberName from "path" + "fileName";
// this will not work!, since "path" + "fileName" need to be string literal
使用以下语法:
let memberName = require("path" + "fileName");
Dynamic import()(在Chrome 63+中可用)将完成您的工作。方法如下:
let variableName = 'test.js';
let utilsPath = './utils/' + variableName;
import(utilsPath).then((module) => { module.something(); });
/utils/test.js
export default () => {
doSomething...
}
从文件调用
const variableName = 'test';
const package = require(`./utils/${variableName}`);
package.default();
我会像这个一样做
function load(filePath) {
return () => System.import(`${filePath}.js`);
// Note: Change .js to your file extension
}
let A = load('./utils/' + variableName)
// Now you can use A in your module
这取决于情况。您可以在动态导入中使用模板文字来导入基于变量的文件。
我使用动态导入将.vue
文件添加到vue路由器。我已排除Home.vue
视图导入。
const pages = [
'About',
['About', 'Team'],
]
const nodes = [
{
name: 'Home',
path: '/',
component: Home,
}
]
for (const page of pages) {
if (typeof page === 'string') {
nodes.push({
name: page,
path: `/${page}`,
component: import(`./views/${page}.vue`),
})
} else {
nodes.push({
name: _.last(page),
path: `/${page.join('/')}`,
component: import(`./views/${_.last(page)}.vue`)
})
}
}
这对我有效。我在replit上使用了yarn+vite+vue。
- 在ES6中加载SASS变量
- 如何检查ES6“;变量“;是恒定的
- 如何执行“变量”ES6导入
- Javascript ES6共享类变量
- ES6/JavaScript-声明不带let/const的变量
- 如何通过名称(从模块本身)访问ES6模块变量
- NodeJS和ES6类实例中的变量可见性
- ES6 类中成员变量的声明
- ES6 循环和 forEach 中的上下文和变量范围
- 使用参数变量获取传递给 ES6 箭头函数的参数
- 在 $resource.query 回调函数中访问类变量时出现 es6 问题
- Javascript 中的静态变量继承 (ES6)
- ES6/ES2015 对象解构和更改目标变量
- 如何在 es6 类中声明私有变量和私有方法
- 使用 ES6 模块重新导出全局变量
- ES6 块范围的变量定义作为条件
- 在 ES6 中导出多个变量
- 如何在Chrome/Firefox中导出ES6中的变量
- 如何从另一个类(编辑:另一个js页面)访问ReactJS渲染中的变量(ES6和Node正在使用)
- 全局声明的顶级变量(ES6 Babel)