是否可以使用通配符从目录中的所有文件导入模块?

Fra*_*bot 220 javascript ecmascript-6 es6-modules

使用ES6,我可以从这样的文件中导入几个导出:

import {ThingA, ThingB, ThingC} from 'lib/things';
Run Code Online (Sandbox Code Playgroud)

但是,我喜欢每个文件有一个模块的组织.我最终得到这样的导入:

import ThingA from 'lib/things/ThingA';
import ThingB from 'lib/things/ThingB';
import ThingC from 'lib/things/ThingC';
Run Code Online (Sandbox Code Playgroud)

我希望能够做到这一点:

import {ThingA, ThingB, ThingC} from 'lib/things/*';
Run Code Online (Sandbox Code Playgroud)

或类似的东西,理解的约定是每个文件包含一个默认导出,并且每个模块的名称与其文件相同.

这可能吗?

Ber*_*rgi 205

我不认为这是可能的,但是模块名称的解析取决于模块加载器,因此可能有一个加载器实现支持这一点.

在此之前,您可以使用lib/things/index.js仅包含的中间"模块文件"

export * from 'ThingA';
export * from 'ThingB';
export * from 'ThingC';
Run Code Online (Sandbox Code Playgroud)

它会让你这样做

import {ThingA, ThingB, ThingC} from 'lib/things';
Run Code Online (Sandbox Code Playgroud)

  • 谢谢您的帮助.我能够使用`index.js`看起来像这样:`从'things/ThingA'导入ThingA; 出口{ThingA as ThingA}; 从'things/ThingB'导入ThingB; export {ThingB as ThingB};`.`index.js`中的其他咒语不会让步. (5认同)
  • 是的,如果每个ThingA.js,ThingB.js都导出了名为exports的原始答案,那么您的原始答案确实有效.发现. (4认同)
  • 嗯,[`export*from`](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-exports-static-semantics-exportentries)应该有效.你有没有试过`...来自'./ ThingA'`或`从......输出ThingA?你使用什么模块加载器? (2认同)
  • @RodrigoMata不,它实际上只是提供了这种分组(和定义的评估顺序,但这很少需要)。 (2认同)

Jed*_*rds 115

只是答案中已经提供的主题的变体,但是如何:

在一个Thing,

export default function ThingA () {}
Run Code Online (Sandbox Code Playgroud)

things/index.js,

export {default as ThingA} from './ThingA'
export {default as ThingB} from './ThingB'
export {default as ThingC} from './ThingC'
Run Code Online (Sandbox Code Playgroud)

然后消耗其他地方的所有东西,

import * as things from './things'
things.ThingA()
Run Code Online (Sandbox Code Playgroud)

或者仅仅消耗一些东西,

import {ThingA,ThingB} from './things'
Run Code Online (Sandbox Code Playgroud)

  • 这是否利用了三摇?如果我确实从 './things' 导入 {ThingA},ThingB 和 ThingC 也会添加到捆绑包中吗? (3认同)
  • 难道你不能简单地从'./ ThingA'中输入'export ThingA'而不是'export ThingA'而不是'export ThingA}. (2认同)

Dow*_*oat 63

目前的答案提示了一种解决方法,但它告诉我为什么这不存在,所以我创建了一个babel插件来执行此操作.

安装使用:

npm i --save-dev babel-plugin-wildcard
Run Code Online (Sandbox Code Playgroud)

然后将其添加到您.babelrc的:

{
    "plugins": ["wildcard"]
}
Run Code Online (Sandbox Code Playgroud)

请参阅回购以获取详细的安装信息


这允许您这样做:

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

// Do whatever you want with these :D
Things.ThingA;
Things.ThingB;
Things.ThingC;
Run Code Online (Sandbox Code Playgroud)

再一次,repo包含有关它究竟是什么的进一步信息,但这样做可以避免创建index.js文件,也可以在编译时发生,以避免readdir在运行时执行.

还有一个更新的版本,你可以像你的例子一样:

 import { ThingsA, ThingsB, ThingsC } from './lib/things/*';
Run Code Online (Sandbox Code Playgroud)

与上述相同.

  • 警告,我对这个插件有严重的问题.问题可能来自它的内部缓存,你会把你的头发拉出来,当你的代码完美,但你的脚本将无法正常工作因为你将文件添加到`./lib/things;`并且它没有被选中起来.它造成的问题是荒谬的.我刚刚目睹了情况,当用`import*'更改文件时,让babel拿起添加的文件,但是将其更改回来会带来问题,就像它在更改之前重新使用缓存一样.谨慎使用. (2认同)

Nic*_*las 9

类似于已接受的问题,但它允许您在每次创建一个新模块时无需向索引文件添加新模块的情况下进行扩展:

./modules/moduleA.js

export const example = 'example';
export const anotherExample = 'anotherExample';
Run Code Online (Sandbox Code Playgroud)

./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;
Run Code Online (Sandbox Code Playgroud)

./example.js

import { example, anotherExample } from './modules'
Run Code Online (Sandbox Code Playgroud)


Mic*_*ole 7

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

导出一个单位默认值

这是使用一个很好的机会传播...{ ...Matters, ...Contacts }下面:

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

Run Code Online (Sandbox Code Playgroud)
// imports/test.js
import collections from './collections';  // import default export as 'collections'

console.log(collections);
Run Code Online (Sandbox Code Playgroud)

然后,从命令行(从项目根目录/)运行babel编译代码

// imports/collections/Matters.js
export default {           // default export
  hello: 'World',
  something: 'important',
};
Run Code Online (Sandbox Code Playgroud)

导出一棵树状默认值

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

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

export default {   // export default
  Matters,
  Contacts,
};
Run Code Online (Sandbox Code Playgroud)

输出将是:

// imports/collections/Contacts.js
export default {           // default export
  hello: 'Moon',
  email: 'hello@example.com',
};
Run Code Online (Sandbox Code Playgroud)

导出多个已命名的导出,没有默认设置

如果您专用于DRY,则导入的语法也会更改:

// imports/collections/index.js

// export default as named export 'Matters'
export { default as Matters } from './Matters';  
export { default as Contacts } from './Contacts'; 
Run Code Online (Sandbox Code Playgroud)

这将创建2个没有默认导出的命名导出。然后更改:

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

console.log(Matters, Contacts);
Run Code Online (Sandbox Code Playgroud)

并输出:

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

Run Code Online (Sandbox Code Playgroud)

导入所有命名的出口

// imports/collections/index.js

// export default as named export 'Matters'
export { default as Matters } from './Matters';
export { default as Contacts } from './Contacts';
Run Code Online (Sandbox Code Playgroud)
// 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);
Run Code Online (Sandbox Code Playgroud)

注意上一个示例中的解构 import { Matters, Contacts } from './collections';

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

console.log(collections);
Run Code Online (Sandbox Code Playgroud)

在实践中

给定这些源文件:

/myLib/thingA.js
/myLib/thingB.js
/myLib/thingC.js
Run Code Online (Sandbox Code Playgroud)

创建一个/myLib/index.js将所有文件捆绑在一起的方法无法达到导入/导出的目的。首先,将所有内容全局化,而不是通过index.js“包装文件”通过导入/导出使全局化。

如果需要特定文件,请import thingA from './myLib/thingA';在自己的项目中。

仅在为npm打包或在多年的多团队项目中打包时,才为模块创建带有导出功能的“包装文件”。

到此为止了吗?有关更多详细信息,请参阅文档

同样,对于Stackoverflow来说,最终支持三个`s作为代码围栏标记。


mr_*_*all 5

您可以使用异步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')
  });
});
Run Code Online (Sandbox Code Playgroud)

  • 动态导入就像这样。当提出问题时,它们肯定不存在。谢谢你的回答。 (3认同)