it-swarm.com.de

Ist es möglich, Module aus allen Dateien eines Verzeichnisses mithilfe eines Platzhalters zu importieren?

Mit ES6 kann ich mehrere Exporte aus einer Datei wie folgt importieren:

import {ThingA, ThingB, ThingC} from 'lib/things';

Ich mag es jedoch, ein Modul pro Datei zu haben. Ich ende mit Importen wie folgt:

import ThingA from 'lib/things/ThingA';
import ThingB from 'lib/things/ThingB';
import ThingC from 'lib/things/ThingC';

Ich würde das gerne tun können:

import {ThingA, ThingB, ThingC} from 'lib/things/*';

oder etwas Ähnliches, mit der bekannten Konvention, dass jede Datei einen Standardexport enthält und jedes Modul denselben Namen wie seine Datei hat.

Ist das möglich?

184
Joe Frambach

Ich denke nicht, dass dies möglich ist, aber die Auflösung der Modulnamen liegt bei den Modulladern. Daher gibt es möglicherweise eine Loader-Implementierung, die dies unterstützt.

Bis dahin können Sie unter lib/things/index.js eine "Moduldatei" verwenden, die gerade enthält

export * from 'ThingA';
export * from 'ThingB';
export * from 'ThingC';

und es würde dir erlauben zu tun

import {ThingA, ThingB, ThingC} from 'lib/things';
173
Bergi

Nur eine Variation des Themas, das bereits in der Antwort angegeben ist, aber wie wäre es damit:

In einem Thing

export default function ThingA () {}

Im things/index.js,

export {default as ThingA} from './ThingA'
export {default as ThingB} from './ThingB'
export {default as ThingC} from './ThingC'

Dann all die Dinge woanders zu konsumieren,

import * as things from './things'
things.ThingA()

Oder um nur einige Dinge zu konsumieren,

import {ThingA,ThingB} from './things'
108
Jed Richards

Die aktuellen Antworten deuten auf eine Problemumgehung hin, aber es ist ein Problem, warum dies nicht existiert. Deshalb habe ich ein babel-Plugin erstellt, das dies tut.

Installieren Sie es mit:

npm i --save-dev babel-plugin-wildcard

dann füge es zu deinem .babelrc hinzu mit:

{
    "plugins": ["wildcard"]
}

ausführliche Informationen zur Installation finden Sie unter repo


Dies ermöglicht Ihnen Folgendes:

import * as Things from './lib/things';

// Do whatever you want with these :D
Things.ThingA;
Things.ThingB;
Things.ThingC;

das repo enthält weitere Informationen darüber, was genau es tut. Wenn Sie dies auf diese Weise tun, vermeiden Sie jedoch die Erstellung von index.js-Dateien und werden auch zur Kompilierzeit ausgeführt, um zu vermeiden, dass readdirs zur Laufzeit ausgeführt wird.

Auch mit einer neueren Version können Sie genau wie Ihr Beispiel machen:

 import { ThingsA, ThingsB, ThingsC } from './lib/things/*';

funktioniert wie oben.

55
Downgoat

Ich habe sie einige Male verwendet (insbesondere zum Erstellen massiver Objekte, die die Daten auf viele Dateien aufteilen (z. B. AST - Knoten)). Um sie zu erstellen, habe ich ein kleines Skript erstellt (das ich gerade hinzugefügt habe.) npm, damit jeder andere es benutzen kann).

Verwendung (derzeit müssen Sie babel verwenden, um die Exportdatei verwenden zu können):

$ npm install -g folder-module
$ folder-module my-cool-module/

Erzeugt eine Datei mit:

export {default as foo} from "./module/foo.js"
export {default as default} from "./module/default.js"
export {default as bar} from "./module/bar.js"
...etc

Dann können Sie die Datei einfach verbrauchen:

import * as myCoolModule from "my-cool-module.js"
myCoolModule.foo()
2
Jamesernator

Nur eine andere Herangehensweise an @ Bergis Antwort

// lib/things/index.js
import ThingA from './ThingA';
import ThingB from './ThingB';
import ThingC from './ThingC';

export default {
 ThingA,
 ThingB,
 ThingC
}

Verwendet

import {ThingA, ThingB, ThingC} from './lib/things';
2

Große gugly Muglys! Das war schwieriger als es sein musste.

Einen Standardwert exportieren

Dies ist eine großartige Gelegenheit, spread (... in { ...Matters, ...Contacts } unten) zu verwenden:

// imports/collections/Matters.js
export default {           // default export
  hello: 'World',
  something: 'important',
};
// imports/collections/Contacts.js
export default {           // default export
  hello: 'Moon',
  email: '[email protected]',
};
// imports/collections/index.js
import Matters from './Matters';      // import default export as var 'Matters'
import Contacts from './Contacts';

export default {  // default export
  ...Matters,     // spread Matters, overwriting previous properties
  ...Contacts,    // spread Contacts, overwriting previosu properties
};

// imports/test.js
import collections from './collections';  // import default export as 'collections'

console.log(collections);

Dann, um babel kompilierten Code über die Befehlszeile auszuführen (vom Projektstammverzeichnis /):

$ npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/node 
(trimmed)

$ npx babel-node --presets @babel/preset-env imports/test.js 
{ hello: 'Moon',
  something: 'important',
  email: '[email protected]' }

Exportieren Sie einen baumartigen Standard

Wenn Sie die Eigenschaften nicht überschreiben möchten, ändern Sie Folgendes:

// imports/collections/index.js
import Matters from './Matters';     // import default as 'Matters'
import Contacts from './Contacts';

export default {   // export default
  Matters,
  Contacts,
};

Und die Ausgabe wird sein:

$ npx babel-node --presets @babel/preset-env imports/test.js
{ Matters: { hello: 'World', something: 'important' },
  Contacts: { hello: 'Moon', email: '[email protected]' } }

Exportieren Sie mehrere benannte Exporte ohne Standard

Wenn Sie sich für DRY interessieren, ändert sich auch die Syntax für die Importe:

// imports/collections/index.js

// export default as named export 'Matters'
export { default as Matters } from './Matters';  
export { default as Contacts } from './Contacts'; 

Dadurch werden 2 benannte Exporte ohne Standardexport erstellt. Dann ändern Sie:

// imports/test.js
import { Matters, Contacts } from './collections';

console.log(Matters, Contacts);

Und die Ausgabe: 

$ npx babel-node --presets @babel/preset-env imports/test.js
{ hello: 'World', something: 'important' } { hello: 'Moon', email: '[email protected]' }

Importieren Sie alle genannten Exporte

// imports/collections/index.js

// export default as named export 'Matters'
export { default as Matters } from './Matters';
export { default as Contacts } from './Contacts';
// imports/test.js

// Import all named exports as 'collections'
import * as collections from './collections';

console.log(collections);  // interesting output
console.log(collections.Matters, collections.Contacts);

Beachten Sie den destructuringimport { Matters, Contacts } from './collections'; im vorherigen Beispiel.

$ npx babel-node --presets @babel/preset-env imports/test.js
{ Matters: [Getter], Contacts: [Getter] }
{ hello: 'World', something: 'important' } { hello: 'Moon', email: '[email protected]' }

In der Praxis

Gegeben diese Quelldateien:

/myLib/thingA.js
/myLib/thingB.js
/myLib/thingC.js

Wenn Sie einen /myLib/index.js erstellen, um alle Dateien zu bündeln, ist der Zweck des Imports/Exports nicht gegeben. Es wäre einfacher, alles global zu machen, als alles durch Import/Export über index.js "Wrapper-Dateien" zu machen.

Wenn Sie eine bestimmte Datei wünschen, import thingA from './myLib/thingA'; in Ihren eigenen Projekten.

Das Erstellen einer "Wrapper-Datei" mit Exporten für das Modul ist nur sinnvoll, wenn Sie für npm oder für ein mehrjähriges Projekt mit mehreren Teams verpacken.

So weit gekommen? Weitere Informationen finden Sie unter docs .

Außerdem unterstützt yay für Stackoverflow endlich drei `s als Code-Zaun-Markup.

1
Michael Cole

Ähnlich wie bei der akzeptierten Frage, jedoch können Sie skalieren, ohne bei jeder Erstellung ein neues Modul zur Indexdatei hinzufügen zu müssen:

./ modules/moduleA.js

export const example = 'example';
export const anotherExample = 'anotherExample';

./ modules/index.js

// require all modules on the path and with the pattern defined
const req = require.context('./', true, /.js$/);

const modules = req.keys().map(req);

// export all modules
module.exports = modules;

./ example.js

import { example, anotherExample } from './modules'
1
Nicolas

Sie können asynchronen Import () verwenden:

import fs = require ('fs');

und dann:

fs.readdir('./someDir', (err, files) => {
 files.forEach(file => {
  const module = import('./' + file).then(m =>
    m.callSomeMethod();
  );
  // or const module = await import('file')
  });
});
1
mr_squall

Sie können auch folgendes verwenden:

const moduleHolder = []

function loadModules(path) {
  let stat = fs.lstatSync(path)
  if (stat.isDirectory()) {
    // we have a directory: do a tree walk
    const files = fs.readdirSync(path)
    let f,
      l = files.length
    for (var i = 0; i < l; i++) {
      f = pathModule.join(path, files[i])
      loadModules(f)
    }
  } else {
    // we have a file: load it
    var controller = require(path)
    moduleHolder.Push(controller)
  }
}

Dann nutzen Sie Ihren moduleHolder mit dynamisch geladenen Controllern:

  loadModules(DIR) 
  for (const controller of moduleHolder) {
    controller(app, db)
  }
0
mr_squall

Das ist nicht genau das, wonach Sie gefragt haben, aber mit dieser Methode kann ich durch componentsList in meinen anderen Dateien iterieren und Funktionen wie componentsList.map(...) verwenden, die ich sehr nützlich finde!

import StepOne from './StepOne';
import StepTwo from './StepTwo';
import StepThree from './StepThree';
import StepFour from './StepFour';
import StepFive from './StepFive';
import StepSix from './StepSix';
import StepSeven from './StepSeven';
import StepEight from './StepEight';

const componentsList= () => [
  { component: StepOne(), key: 'step1' },
  { component: StepTwo(), key: 'step2' },
  { component: StepThree(), key: 'step3' },
  { component: StepFour(), key: 'step4' },
  { component: StepFive(), key: 'step5' },
  { component: StepSix(), key: 'step6' },
  { component: StepSeven(), key: 'step7' },
  { component: StepEight(), key: 'step8' }
];

export default componentsList;
0
FlyingZipper