it-roy-ru.com

Можно ли импортировать модули из всех файлов в каталоге, используя подстановочный знак?

С ES6 я могу импортировать несколько экспортов из файла, подобного этому:

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

Тем не менее, мне нравится организация одного модуля на файл. Я получаю импорт, как это:

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

Я хотел бы быть в состоянии сделать это:

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

или что-то подобное, с понятным соглашением, что каждый файл содержит один экспорт по умолчанию, и каждый модуль называется так же, как его файл.

Это возможно?

184
Joe Frambach

Я не думаю, что это возможно, но на самом деле разрешение имен модулей зависит от загрузчиков модулей, так что может быть реализация загрузчика, которая поддерживает это.

До этого вы могли бы использовать промежуточный «файл модуля» в lib/things/index.js, который просто содержит

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

и это позволит вам сделать

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

Просто вариация на тему уже указана в ответе, но как на счет этого:

В Thing,

export default function ThingA () {}

В things/index.js,

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

Затем потреблять все вещи в другом месте,

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

Или потреблять только некоторые вещи,

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

Текущие ответы предлагают обходной путь, но меня беспокоит, почему этого не существует, поэтому я создал плагин babel, который делает это.

Установите его, используя:

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

затем добавьте его в свой .babelrc с помощью:

{
    "plugins": ["wildcard"]
}

см. repo для подробной информации об установке


Это позволяет вам сделать это:

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

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

опять же, repo содержит дополнительную информацию о том, что именно он делает, но при этом он избегает создания файлов index.js и также происходит во время компиляции, чтобы избежать выполнения readdirs во время выполнения.

Также с более новой версией вы можете сделать так же, как ваш пример:

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

работает так же, как и выше.

55
Downgoat

Я использовал их несколько раз (в частности, для создания массивных объектов, разделяющих данные по множеству файлов (например, AST)), чтобы создать их, я создал крошечный скрипт (который я только что добавил в так что все остальные могут его использовать).

Использование (в настоящее время вам нужно использовать babel для использования файла экспорта):

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

Создает файл, содержащий:

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

Тогда вы можете просто использовать файл:

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

Просто другой подход к ответу @ Берги

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

export default {
 ThingA,
 ThingB,
 ThingC
}

Пользы

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

Великие гугли магглы! Это было сложнее, чем нужно было.

Экспортировать одну квартиру по умолчанию

Это отличная возможность использовать распространение (... в { ...Matters, ...Contacts } ниже:

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

Затем, чтобы запустить скомпилированный код babel из командной строки (из корня проекта /):

$ 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]' }

Экспорт одного древовидного по умолчанию

Если вы не хотите перезаписывать свойства, измените:

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

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

И на Результате будет:

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

Экспорт нескольких именованных экспортов без по умолчанию

Если вы посвящены DRY , синтаксис импорта также меняется:

// imports/collections/index.js

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

Это создает 2 именованных экспорта без экспорта по умолчанию. Затем измените:

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

console.log(Matters, Contacts);

И вывод: 

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

Импортировать все именованные экспорты

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

Обратите внимание на destructuringimport { Matters, Contacts } from './collections'; в предыдущем примере.

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

На практике

Учитывая эти исходные файлы:

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

Создание /myLib/index.js для связывания всех файлов отменяет цель импорта/экспорта. Во-первых, было бы проще сделать все глобальным, чем сделать все глобальным с помощью импорта/экспорта через index.js «файлы-оболочки».

Если вы хотите определенный файл, import thingA from './myLib/thingA'; в ваших собственных проектах.

Создание «файла-оболочки» с экспортом для модуля имеет смысл только в том случае, если вы собираете пакет для npm или в многолетнем многопользовательском проекте.

Сделал это так далеко? Смотрите документы для более подробной информации.

Кроме того, yay для Stackoverflow, наконец, поддерживает три в качестве разметки кода.

1
Michael Cole

Вы можете использовать асинхронный импорт ():

import fs = require ('fs');

а потом:

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

Вы также можете использовать require:

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)
  }
}

Затем используйте свой moduleHolder с динамически загружаемыми контроллерами:

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

Это не совсем то, о чем вы просили, но с помощью этого метода я могу перебирать componentsList в других моих файлах и использовать функцию, такую ​​как componentsList.map(...), которая я считаю довольно полезной!

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