2015-03-20 5 views
69

ist es möglich, etwas in das Modul zu importieren, das den Variablennamen während des ES6-Imports liefert?ES6 Variable importieren Name in node.js?

I.e. Ich mag einige Modul bei einer Laufzeit importiert abhängig von Werten in einer Config zur Verfügung gestellt:

import something from './utils/' + variableName; 
+0

Haben Sie es versucht? – Bigood

+0

@Bigood ja, Compiler wirft auf und Webstorm zeigt auch einen Fehler –

Antwort

43

Nicht mit der import Aussage. import und export sind so definiert, dass sie statisch auswertbar sind, so dass sie nicht auf Laufzeitinformationen angewiesen sind.

Sie suchen die loader API (polyfill), aber ich bin ein wenig unklar über den Stand der Spezifikation:

System.import('./utils/' + variableName).then(function(m) { 
    console.log(m); 
}); 
+2

Muss ich System "erfordern"? Es ist nicht auf globaler Ebene .. Ps.s. Ich benutze Babel js –

+0

Es ist noch nirgendwo AFAIK implementiert. Sie müssen das Polyfill über den Link verwenden. –

+0

Nur überprüft, funktioniert es (versucht das Laden der Datei), aber dann vermasselt Pfade für andere Module ... Schade, es wird nicht nativ unterstützt. –

21

Neben Felix's answer, ich werde ausdrücklich beachten Sie, dass dies derzeit nicht von der erlaubt ECMAScript 6 grammar:

ImportDeclaration:

  • importierenImportClause FromClause;

  • ImportModuleSpecifier;

FromClause:

  • vonModuleSpecifier

ModuleSpecifier:

  • Zeichenketten-Literale

A ModuleSpecifier kann nur eine Zeichenketten-Literale , nicht irgendeine andere Art von Ausdruck wie ein AdditiveExpression.

+0

Es ist schade, dass dies nicht erweitert wurde, um 'const'' String-Literale 'zu enthalten. Sie sind statisch analysierbar, oder? Es würde die Wiederverwendung der Position einer Abhängigkeit zu einer Möglichkeit machen. (z. B. eine Vorlage importieren und sowohl die Vorlage als auch den Speicherort der Vorlage verfügbar haben). – nicodemus13

11

Während dies nicht wirklich ein dynamischer Import ist (zB in meinem Fall werden alle Dateien, die ich unten importiere, von webpack importiert und gebündelt, zur Laufzeit nicht ausgewählt), ein Muster, das ich benutzt habe Unter bestimmten Umständen ist:

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

const templates = { 
    Template1, 
    Template2 
}; 

export function getTemplate (name) { 
    return templates[name]; 
} 

oder alternativ:

// 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; 

ich glaube nicht, dass ich mit require() so leicht wieder auf einen Standard fallen kann, die einen Fehler aus, wenn ich versuche, einen konstruiert zu importieren Vorlagenpfad, der nicht existiert.

Gute Beispiele und Vergleiche zwischen erfordern und Import ist hier zu finden: http://www.2ality.com/2014/09/es6-modules-final.html

Hervorragende Dokumentation der Wiederausfuhr von @iainastacio: http://exploringjs.com/es6/ch_modules.html#sec_all-exporting-styles

Ich bin interessiert Feedback zu diesem Ansatz zu hören :)

+0

Tx für die Bearbeitung @ianastacio! Wie habe ich das vermisst ?! – ptim

3

können Sie die Nicht-ES6-Notation dazu verwenden. das ist, was für mich gearbeitet:

let myModule = null; 
if (needsToLoadModule) { 
    myModule = require('my-module').default; 
} 
3

ich weniger wie diese Syntax, aber es funktioniert:
statt

import memberName from "path" + "fileName"; 
// this will not work!, since "path" + "fileName" need to be string literal 

verwenden diese Syntax zu schreiben:

let memberName = require("path" + "fileName"); 
+0

dies ist nicht nur eine andere Syntax, sondern ein anderes Verhalten. –

+0

required ist nicht gleich importieren. Sie sind anders –

0

ich tun würde, es ist so

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 
-1

Mit ES6 Vorlage Strings ich auf den Import dynamisch Variablen gelungen war, hier ist mein boilerplate - hier geht es um universelle Javascript, aber es sollte auf verschiedenen Konfigurationen arbeiten:

const myImg = './cute.jpg' 
<img src={require(`${myImg}`)} /> 
2

Es gibt eine neue Spezifikation, die ein genannt wird dynamischer Import für ES-Module. Im Grunde rufen Sie einfach import('./path/file.js') und Ihr Gut zu gehen. Die Funktion gibt eine Zusage zurück, die mit dem Modul aufgelöst wird, wenn der Import erfolgreich war.

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

Wichtige Anwendungsfälle Route basiertes Modul umfassen für Polymer Import 3.0, Reaktion und Vue, die Download-Bandbreite reduziert, da das Bündel für die Routen sind nur dann geladen, wenn sie erforderlich sind.

Hier ist die vorgeschlagene Spezifikation auf Github.

Derzeit (Januar 2017) funktioniert diese Funktion in Chrome 62. Die anderen großen Browser greifen diese Funktion wahrscheinlich auf und implementieren sie später, wenn die ESmodule-Unterstützung vollständig unterstützt wird.

Edit:
Ich soll hinzufügen, dass der spec Einfuhren statisch analysierbar sein erfordert, sowohl den regulären Import als auch den dynamischen Import, was bedeutet, dass Sie nicht einen Variablennamen verwenden können, um Ihren Importpfad zu erklären . Es gibt also keine Lösung für Ihre Frage, weil die ES-Spezifikation das durch Design verhindert.