我看到一些我继承的代码存在一个模式。每个目录都有自己的JS文件,但是还有一个名为index.js的文件,实际上从其他JS文件中导出项目。
我认为这样做是为了确切地知道你正在导出什么,因为主要的导出都在index.js中,而主要的代码在其他js文件中。
这个模式叫什么?这正确吗?
我应该继续使用这个模式吗?
我看到一些我继承的代码存在一个模式。每个目录都有自己的JS文件,但是还有一个名为index.js的文件,实际上从其他JS文件中导出项目。
我认为这样做是为了确切地知道你正在导出什么,因为主要的导出都在index.js中,而主要的代码在其他js文件中。
这个模式叫什么?这正确吗?
我应该继续使用这个模式吗?
假设我有以下目录结构:
MyApp
├── app.js
├── test.js
├── package.json
├─┬ controllers
│ ├── index.js
│ ├── signIn.js
│ └── signOut.js
└─┬ views
├── index.js
├── signIn.js
└── signOut.js
将下面的代码放入index.js
文件中...
// index.js
module.exports = {
signIn: require('./signIn')
, signOut: require('./signOut')
};
...允许你像require
一个完整的目录一样...
// test.js
describe('controllers', () => {
// ~/controllers/index.js
const controllers = require('./controllers');
it('performs a sign-in', () => {
...
});
it('performs a sign-out', () => {
...
});
});
另一种选择是逐个“require”每个文件。
在目录中拥有一个“index.js”并非必须。即使没有“index.js”,您也可以“require”目录中的文件。
// app.js
const signOut = require('./controllers/signOut.js')
然而,随着您的应用程序增长,这变得很繁琐。我使用类似require-directory
这样的包,因为在目录中键入每个文件也很繁琐且有些容易出错。
// index.js
module.exports = require('require-directory')(module);
/*
This yields the same result as:
module.exports = {
signIn: require('./signIn')
, signOut: require('./signOut')
, ...
};
*/
考虑到这两种常见的结构...
MyApp
│ // files divided per type (controllers, components, actions, ...)
├─┬ actions
│ ├── index.js
│ ├── signIn.js
│ └── signOut.js
├─┬ components ...
├─┬ reducers ...
├─┬ pages ...
│
│ // files divided per component
├─┬ components ...
│ ├── index.js
│ ├── SimpleComponent.jsx
│ ├── AnotherComponent.duck.jsx // redux "duck" pattern
│ ├─┬ ComplexComponent // large complex logic, own actions, stylesheet, etc.
│ ...
├─┬ pages ...
│ ├── index.js
│ ├─┬ App
│ │ ├── index.js // not necessary here, matter of habit
│ │ ├── App.jsx
│ │ ├── actions.js
│ │ └── reducer.js
│ └─┬ Dashboard
├── another.js
...
您可以像这样简单地导入another.js
中的文件
import {signIn, signOut} from './actions'
import {App} from './pages'
import {ComplexComponent} from './components'
不使用index.js
文件,应该这样做:(without index.js
files)
import {signIn} from './actions/signIn'
import {signOut} from './actions/signOut'
import {App} from './pages/App/App' //notice the redundancy here
import {ComplexComponent} from './components/ComplexComponent/ComplexComponent'
ECMAScript 6 模块
import - JavaScript | MDN
Babel 转译器 - 现在可以将新的 import 引入您的浏览器中了
组织 React 项目
React Redux "Ducks pattern" - 组件的单文件解决方案
其他答案提供了很多很棒的信息,但是特别回答你的问题“我是否应该继续使用这种模式”,我会说不,至少大部分情况下是这样。
问题在于,这种模式需要额外的工作,因为你必须维护那些额外的index.js
文件。在我的经验中,这种努力比只需编写一个目录更长的import
语句所需的努力更大。此外,通过使用诸如require-dir
之类的模块,您可以获得与具有index.js
相同的功能而无需使用它。
尽管如此,如果你正在制作将由大量人使用的库,例如大型编程部门中的关键模块或公共NPM模块,则index.js
的努力变得更加合理。只要有足够的人使用你的模块,你添加它们比你维护它们会节省更多的时间。
我将直接回答您是否应该使用这种模式的问题(因为其他答案对此不够充分)。
假设你代码中的每个目录都表示一个独立的模块(不依赖于其他模块工作)。使用这种模式将带来以下优点:
以下是这种模式的问题:
循环依赖非常棘手,使用index.js
导入整个模块/目录将导入其中声明在index.js
中的所有部分。因此,如果您有以下内容:
-- moduleA
├-- comp1A // needs comp1B
├-- comp2A
└-- index.js // export both comp1/2
-- moduleB
├-- comp1B
├-- comp2B // needs comp2A
└-- index.js // export both comp1/2
示例案例 - comp1A
需要来自 comp1B
的内容,而 comp2B
需要来自 comp2A
的内容。
当导入特定文件(不带有 index.js
- import something from './moduleB/comp1B'
)时,您将不会出现循环依赖。
但是,如果您使用 index.js
(import something from './moduleB'
),则会发生循环依赖。
我建议在正确的地方使用 index.js
并保持维护!对于小模块使用 index.js
将非常完美,但随着时间的推移,它们将会增长并需要被拆分开来。在整个项目中使用公共 / 共享 / 工具 / 杂项 / 核心(无论您称其为何种未分类和不相关的代码)模块时,使用 index.js
是非常糟糕的。
module.exports = {
...require('./moduleA'),
...require('./moduleB')
}
(moduleA.a将被moduleB.a覆盖)