Wie führt man einen „variablen“ ES6-Import durch?

Lesezeit: 6 Minuten

Benutzeravatar von Vytautas Butkus
Vytautas Butkus

Ist es möglich, etwas in ein Modul zu importieren, das einen Variablennamen bereitstellt, während der ES6-Import verwendet wird?

Das heißt, ich möchte ein Modul zur Laufzeit importieren, abhängig von den in einer Konfiguration angegebenen Werten:

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

Beachten Sie, dass ich Node.js verwende, aber Antworten müssen die Kompatibilität mit ECMAScript-Modulen berücksichtigen.

  • @Bigood ja, der Compiler wirft hoch und Webstorm zeigt auch einen Fehler

    – Vytautas Butkus

    20. März 2015 um 14:10 Uhr

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

Sie suchen die Loader-API (Polyfill)aber ich bin etwas unklar über den Status der Spezifikation:

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

  • muss ich das System “erfordern”? Es ist nicht auf globaler Ebene. Ps. Ich verwende babel js

    – Vytautas Butkus

    20. März 2015 um 14:13 Uhr


  • Es ist AFAIK noch nirgendwo implementiert. Sie müssen die Polyfill aus dem Link verwenden.

    – Felix Klinge

    20. März 2015 um 14:13 Uhr


  • Gerade überprüft, es funktioniert irgendwie (versucht, die Datei zu laden), bringt dann aber Pfade für andere Module durcheinander … Schade, dass es nicht nativ unterstützt wird.

    – Vytautas Butkus

    20. März 2015 um 14:26 Uhr

  • Ist das immer noch ein Problem? Ich muss ES6-Module dynamisch laden, aber ich hatte keinen Erfolg.

    – Calberts

    6. Februar 2016 um 7:31 Uhr

  • Während dies 2015 die beste Antwort war, dynamisch import() wurde in ES2020 standardisiert und wird von Node.js und allen modernen Browsern unterstützt, siehe diese Antwort.

    – TJ Crowder

    9. Januar um 11:08 Uhr

Benutzeravatar von ptim
ptim

Während dies eigentlich kein dynamischer Import ist (z. B. werden in meinem Fall alle Dateien, die ich unten importiere, von Webpack importiert und gebündelt, nicht zur Laufzeit ausgewählt), ist ein Muster, das ich verwendet habe und das unter bestimmten Umständen hilfreich sein kann :

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 so einfach auf einen Standard zurückgreifen kann require()was einen Fehler auslöst, wenn ich versuche, einen konstruierten Vorlagenpfad zu importieren, der nicht existiert.

Gute Beispiele und Vergleiche zwischen require und import finden Sie hier: http://www.2ality.com/2014/09/es6-modules-final.html

Hervorragende Dokumentation zum Re-Export von @iainastacio:
http://exploringjs.com/es6/ch_modules.html#sec_all-exporting-styles

Ich bin gespannt auf Feedback zu diesem Ansatz 🙂

  • Stimme zu. Ich habe den “oder alternativ”-Ansatz verwendet. Funktionierte wie ein Zauber für meine benutzerdefinierte Lokalisierungslösung.

    – groundh0g

    24. Dezember 2018 um 2:29 Uhr

  • React docs: Auswahl des Typs zur Laufzeit

    – ptim

    21. Januar 2020 um 8:57 Uhr


  • Daran hätte ich denken sollen. Großartige Lösung, egal wie Sie Dinge importieren (und selbst wenn Sie nichts importieren). Haben Sie eine Liste mit Artikeln, deren Namen Sie später erhalten möchten? Setzen Sie sie in ein Objektliteral statt in ein Array-Literal, und lassen Sie die Objektsyntax dafür sorgen, dass sie auf der Grundlage ihres lokalen Konstanten-/Variablennamens benannt werden. Wenn Sie sie erneut als Liste benötigen, tun Sie dies einfach Object.values(templates).

    – Andreas Köster

    11. Juni 2020 um 22:40 Uhr


  • Danke, dies ist eine großartige Möglichkeit, dieses Problem einfach zu lösen. Sehr geschätzt.

    – DrCord

    20. Januar 2021 um 23:16 Uhr

Benutzeravatar von Nicolai Schmid
Nicolai Schmidt

Es gibt eine neue Spezifikation namens a Dynamischer Import für ES-Module. Im Grunde rufst du einfach an import('./path/file.js') und du bist gut zu gehen. Die Funktion gibt ein Promise zurück, das mit dem Modul aufgelöst wird, wenn der Import erfolgreich war.

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

Anwendungsfälle

Zu den Anwendungsfällen gehören Routenbasierter Komponentenimport für React, Vue usw. und die Fähigkeit dazu Lazy-Load-Modulesobald sie zur Laufzeit benötigt werden.

Weitere Informationen

Hier ist eine Erklärung dazu Google-Entwickler.

Browserkompatibilität (April 2020)

Entsprechend MDN es wird von allen aktuellen gängigen Browsern (außer IE) unterstützt und caniuse.com zeigt 87 % Unterstützung über den globalen Marktanteil. Wieder keine Unterstützung in IE oder Nicht-Chrom-Edge.

  • Bist du dir sicher mit deiner Bearbeitung? Der Vorschlag zeigt ein Beispiel mit einem variablen Pfad: github.com/tc39/proposal-dynamic-import#example

    – phil294

    7. Mai 2018 um 14:45 Uhr

  • @Blauhirn war ich, aber dein Link zeigt deutlich, dass es eine Möglichkeit ist. Obwohl ich keine Ahnung habe, wie beispielsweise Webpack diese Importe lösen würde

    – Nicolai Schmid

    7. Mai 2018 um 15:31 Uhr

  • Korrigieren Sie mich, wenn ich falsch liege, aber Webpack verarbeitet diese nicht, oder? Ich dachte, es sei der Sinn dynamischer Importe, dass sie “wie sie sind” im Browser ausgeführt werden.

    – phil294

    7. Mai 2018 um 16:19 Uhr

  • Ja, Sie können sie unverändert im Browser ausführen. Aber webpack verwendet die Importe automatisch, um Ihre App in mehrere Bundles für verschiedene Teile Ihrer App aufzuteilen, beispielsweise für Routen. Ich benutze sie die ganze Zeit und sie sind wirklich hilfreich. Und was “Verarbeitung” angeht; webpack übergibt die Importe an babel, wodurch die Funktion für ältere Browser polyfill wird.

    – Nicolai Schmid

    7. Mai 2018 um 16:22 Uhr


  • Um es klar zu sagen: dynamischer Import () Wille arbeitet mit Variablen und muss nicht statisch analysierbar sein (das ist doch der Sinn von „dynamisch“?). Siehe meine Antwort.

    – Velojet

    25. Januar 2019 um 2:42 Uhr

Benutzeravatar von apsillers
Apsiller

Ergänzend zu Felix’ Antwort weise ich ausdrücklich darauf hin, dass dies derzeit von der nicht erlaubt ist ECMAScript 6-Grammatik:

Importdeklaration :

  • importieren ImportKlausel FromClause ;

  • importieren Modulspezifizierer ;

FromClause :

  • aus ModuleSpecifier

ModuleSpecifier :

  • StringLiteral

EIN ModuleSpecifier kann nur ein sein StringLiteralnicht irgendeine andere Art von Ausdruck wie ein AdditiverAusdruck.

Ich verstehe die speziell für ES6 gestellte Frage import in Node.js, aber das Folgende könnte anderen helfen, die nach einer allgemeineren Lösung suchen:

let variableName = "es5.js";
const something = require(`./utils/${variableName}`);

Beachten Sie, ob Sie ein ES6-Modul importieren und müssen auf die zugreifen default exportieren, müssen Sie eine der folgenden Methoden verwenden:

let variableName = "es6.js";

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

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

Sie können bei diesem Ansatz auch die Destrukturierung verwenden, was zu mehr Syntaxvertrautheit mit Ihren anderen Importen führen kann:

// Destructuring 
const { someMethod } = require(`./utils/${variableName}`);    
someMethod();

Leider, wenn Sie zugreifen möchten default Neben der Destrukturierung müssen Sie dies in mehreren Schritten durchführen:

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

mlevanons Benutzeravatar
mlevanon

Sie können dazu die Nicht-ES6-Notation verwenden. das hat bei mir funktioniert:

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

Benutzeravatar von stanimirsp
Stanimirsp

Ich hatte ein ähnliches Problem mit Vue.js: Wenn Sie Variable in verwenden import(variableName) Zur Bauzeit weiß Webpack nicht, wo es suchen soll. Sie müssen es also auf den bekannten Pfad mit der entsprechenden Erweiterung wie folgt beschränken:

let something = import("@/" + variableName + ".js") 

Dass Antwort in GitHub für das gleiche Problem war sehr hilfreich für mich.

1434630cookie-checkWie führt man einen „variablen“ ES6-Import durch?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy