使用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/*';

或者类似的东西,按照大家理解的约定,每个文件包含一个默认导出,每个模块与其文件同名。

这可能吗?


当前回答

如果你使用webpack。这将自动导入文件并导出为api命名空间。

所以不需要更新每一个文件添加。

import camelCase from "lodash-es";
const requireModule = require.context("./", false, /\.js$/); // 
const api = {};

requireModule.keys().forEach(fileName => {
  if (fileName === "./index.js") return;
  const moduleName = camelCase(fileName.replace(/(\.\/|\.js)/g, ""));
  api[moduleName] = {
    ...requireModule(fileName).default
  };
});

export default api;

对于Typescript用户;

import { camelCase } from "lodash-es"
const requireModule = require.context("./folderName", false, /\.ts$/)

interface LooseObject {
  [key: string]: any
}

const api: LooseObject = {}

requireModule.keys().forEach(fileName => {
  if (fileName === "./index.ts") return
  const moduleName = camelCase(fileName.replace(/(\.\/|\.ts)/g, ""))
  api[moduleName] = {
    ...requireModule(fileName).default,
  }
})

export default api

其他回答

太棒了!这比需要的要难。

导出一个平面默认值

这是一个很好的机会来使用传播(…在{……很重要,…联系方式如下:

// imports/collections/Matters.js
export default {           // default export
  hello: 'World',
  something: 'important',
};
// imports/collections/Contacts.js
export default {           // default export
  hello: 'Moon',
  email: 'hello@example.com',
};
// 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: 'hello@example.com' }

导出一个树形默认值

如果您不希望覆盖属性,请更改:

// 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: 'hello@example.com' } }

导出多个命名的导出w/ no默认

如果你专注于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: 'hello@example.com' }

导入所有指定的导出项

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

注意'./collections'中的解构导入{Matters, Contacts};在前面的例子中。

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

在实践中

给定这些源文件:

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

创建一个/myLib/index.js来捆绑所有的文件,这违背了导入/导出的目的。首先让所有内容都全局化要比通过index.js“包装文件”的导入/导出来使所有内容都全局化容易得多。

如果你想要一个特定的文件,从'./myLib/thingA'导入thingA;在你们自己的项目中。

只有当你在为npm或一个多年的多团队项目打包时,为模块创建带有导出的“包装器文件”才有意义。

走了这么远?更多细节请参阅文档。

此外,Stackoverflow终于支持三个作为代码围栏标记。

如果你不导出A, B, C中的默认值,而只是导出{},那么这是可能的

// things/A.js
export function A() {}

// things/B.js
export function B() {}

// things/C.js
export function C() {}

// foo.js
import * as Foo from ./thing
Foo.A()
Foo.B()
Foo.C()

你现在可以使用async import():

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

Nodejs吗?这样做:

用index.js创建一个文件夹,在索引文件中添加以下内容:

var GET = require('./GET');
var IS = require('./IS');
var PARSE = require('./PARSE');
module.exports = { ...GET, ...IS, ...PARSE};

并且,在GET.js或IS.js文件中正常导出:

module.exports = { /* something as you like */}

现在,你只需要像这样包含index.js:

const Helper = require('./YourFolder');

Helper将包括你文件夹中的所有功能。

美好的一天!

我可以借鉴用户atilkan的方法并稍加修改:

对于Typescript用户;

require.context('@/folder/with/modules', false, /\.ts$/).keys().forEach((fileName => {
    import('@/folder/with/modules' + fileName).then((mod) => {
            (window as any)[fileName] = mod[fileName];
            const module = new (window as any)[fileName]();

            // use module
});

}));