173

是否可以将选项传递给 ES6 导入?

你怎么翻译这个:

var x = require('module')(someoptions);

到 ES6?

4

8 回答 8

127

没有办法用单个import语句来做到这一点,它不允许调用。

所以你不会直接调用它,但你基本上可以做与 commonjs 对默认导出所做的一样的事情:

// module.js
export default function(options) {
    return {
        // actual module
    }
}

// main.js
import m from 'module';
var x = m(someoptions);

或者,如果您使用支持单子承诺的模块加载器,您可能可以执行类似的操作

System.import('module').ap(someoptions).then(function(x) {
    …
});

有了新的import运营商,它可能会变成

const promise = import('module').then(m => m(someoptions));

或者

const x = (await import('module'))(someoptions)

但是您可能不想要动态导入而是静态导入。

于 2015-04-28T15:55:56.297 回答
26

概念

这是我使用 ES6 的解决方案

与@Bergi 的响应非常一致,这是我在创建需要为class声明传递参数的导入时使用的“模板”。这用于我正在编写的同构框架,因此将与浏览器和 node.js 中的转译器一起使用(我使用Babelwith Webpack):

./MyClass.js

export default (Param1, Param2) => class MyClass {
    constructor(){
        console.log( Param1 );
    }
}

./main.js

import MyClassFactory from './MyClass.js';

let MyClass = MyClassFactory('foo', 'bar');

let myInstance = new MyClass();

以上将foo在控制台中输出

编辑

现实世界的例子

对于一个真实的例子,我使用它来传递一个命名空间来访问框架中的其他类和实例。因为我们只是创建一个函数并将对象作为参数传入,所以我们可以将它与我们的类声明一起使用,如下所示:

export default (UIFramework) => class MyView extends UIFramework.Type.View {
    getModels() {
        // ...
        UIFramework.Models.getModelsForView( this._models );
        // ...
    }
}

导入有点复杂,automagical在我的情况下,考虑到它是一个完整的框架,但基本上这就是正在发生的事情:

// ...
getView( viewName ){
    //...
    const ViewFactory = require(viewFileLoc);
    const View = ViewFactory(this);
    return new View();
}
// ...

我希望这有帮助!

于 2016-02-16T21:15:27.607 回答
13

以@Bergi 的答案为基础,使用 es6 使用调试模块将如下所示

// original
var debug = require('debug')('http');

// ES6
import * as Debug from 'debug';
const debug = Debug('http');

// Use in your code as normal
debug('Hello World!');
于 2017-04-04T16:33:35.670 回答
5

我已经登陆这个线程,寻找一些类似的东西,并想提出一种解决方案,至少在某些情况下(但请参阅下面的备注)。

用例

我有一个模块,它在加载后立即运行一些实例化逻辑。我喜欢在模块之外调用这个初始化逻辑(这与 callnew SomeClass(p1, p2)new ((p1, p2) => class SomeClass { ... p1 ... p2 ... })类似)。

我确实喜欢这个初始化逻辑将运行一次,一种单一的实例化流程,每个特定的参数化上下文运行一次。

例子

service.js具有非常基本的范围:

let context = null;                  // meanwhile i'm just leaving this as is
console.log('initialized in context ' + (context ? context : 'root'));

模块 A 可以:

import * as S from 'service.js';     // console has now "initialized in context root"

模块 B 执行以下操作:

import * as S from 'service.js';     // console stays unchanged! module's script runs only once

到目前为止一切顺利:两个模块都可以使用服务,但只初始化了一次。

问题

如何让它作为另一个实例运行并在另一个上下文中再次初始化自己,比如在模块 C 中?

解决方案?

这就是我正在考虑的:使用查询参数。在服务中,我们将添加以下内容:

let context = new URL(import.meta.url).searchParams.get('context');

模块 C 会做:

import * as S from 'service.js?context=special';

模块将被重新导入,它的基本初始化逻辑将运行,我们将在控制台中看到:

initialized in context special

备注:我自己建议不要过多地练习这种方法,而是把它作为最后的手段。为什么?多次导入的模块更多的是例外而不是规则,因此它有些出乎意料的行为,因此可能会使消费者感到困惑甚至打破它自己的“单例”范式(如果有的话)。

于 2019-06-24T20:05:22.057 回答
4

我相信你可以使用 es6 模块加载器。 http://babeljs.io/docs/learn-es6/

System.import("lib/math").then(function(m) {
  m(youroptionshere);
});
于 2015-04-28T16:18:38.503 回答
4

您只需要添加这两行。

import xModule from 'module';
const x = xModule('someOptions');
于 2018-06-25T07:35:09.787 回答
2

这是我以调试模块为例对这个问题的看法;

在这个模块的 npm 页面上,你有这个:

var debug = require('debug')('http')

在上面的行中,一个字符串被传递给导入的模块,以进行构造。这是你在 ES6 中做同样事情的方法


import { debug as Debug } from 'debug' const debug = Debug('http');


希望这可以帮助那里的人。

于 2018-10-11T08:27:13.720 回答
1

require()我在尝试将一些 CJS ( ) 代码转换为 ESM ( )时遇到了类似的语法问题import- 这是我需要导入 Redis 时起作用的方法:

CJS

const RedisStore = require('connect-redis')(session);

ESM 等效

import connectRedis from 'connect-redis';
const RedisStore = connectRedis(session);
于 2021-12-12T06:54:47.383 回答