簡體   English   中英

將選項傳遞給 ES6 模塊導入

[英]Pass options to ES6 module imports

是否可以將選項傳遞給 ES6 導入?

你怎么翻譯這個:

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

ES6?

使用單個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)

但是您可能不想要動態導入而是靜態導入。

概念

這是我使用 ES6 的解決方案

與@Bergi 的響應非常一致,這是我在創建需要為class聲明傳遞參數的導入時使用的“模板”。 這用於我正在編寫的同構框架,因此將在瀏覽器和 node.js 中使用轉譯器(我將BabelWebpack一起使用):

./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();
}
// ...

我希望這有幫助!

以@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!');

我已經登陸這個線程,尋找一些類似的東西,並想提出一種解決方案,至少在某些情況下(但請參閱下面的備注)。

用例

我有一個模塊,它在加載后立即運行一些實例化邏輯。 喜歡在模塊外部調用這個初始化邏輯(這與 call new 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

備注:我自己建議不要過多地練習這種方法,而是把它作為最后的手段。 為什么? 多次導入的模塊更多的是例外而不是規則,因此它有些出乎意料的行為,因此可能會使消費者感到困惑甚至破壞它自己的“單例”范式(如果有的話)。

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

System.import("lib/math").then(function(m) {
  m(youroptionshere);
});

您只需要添加這兩行。

import xModule from 'module';
const x = xModule('someOptions');

這是我以調試模塊為例對這個問題的看法;

在這個模塊的 npm 頁面上,你有這個:

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

在上面的行中,一個字符串被傳遞給導入的模塊,以進行構造。 這是你在 ES6 中做同樣事情的方法

import { debug as Debug } from 'debug'

const debug = Debug('http');

希望這可以幫助那里的人。

我在嘗試將一些 CJS ( require() ) 代碼轉換為 ESM ( import ) 時遇到了一個類似的語法問題 - 這是我需要導入 Redis 時的工作:

CJS

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

ESM 等效

import connectRedis from 'connect-redis';
const RedisStore = connectRedis(session);

您可以直接在模塊說明符中傳遞參數:

import * as Lib from "./lib?foo=bar";

參見: https://flaming.codes/en/posts/es6-import-with-parameters

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM