使用'循环'访问顶级文件范围内的导入模块依赖?

时间:2017-10-31 17:00:38

标签: javascript reactjs webpack es6-modules

我有以下模块结构:

/components
├── Button.js
├── Checkbox.js
├── index.js
├── DateSelect
    ├── DateSelect.js
    └── index.js

使用/components/DateSelect/index.js

import DateSelect from './DateSelect';

export default DateSelect;

/components/index.js

import DateSelect from './DateSelect';
import Button from './Button';
import Checkbox from './Checkbox';

export {
  DateSelect,
  Button,
  Checkbox,
};

/components/DateSelect/DateSelect.js

import { Checkbox } from '../';
// ...code

// I want to do this!
const MyCustomCheckbox = props => <Checkbox style={someStyle} />;

// ...code
class DateSelect extends React.Component {
  // code
}
export default DateSelect;

现在,我想访问上面代码中的Checkbox,在文件的顶级范围内,但我得到undefined。但是,如果我在render的{​​{1}}方法中访问此变量,则会按预期工作。

我不完全确定为什么会这样,或者我如何解决这个问题(我可以做DateSelect,但我不想改变使用{的模式{1}}目录的文件),我也想知道究竟发生了什么。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您的问题是您对/components/index.js中的导出存在循环依赖关系。

当您的构建工具首次构建应用程序时,它会执行以下操作...

  • app.js开始,从DateSelect
  • 导入components/index.js
  • 转到声明其导出的components/index.js

    // SPOILER: This guy is your problem. We'll call him the douche.
    export {
      DateSelect,
      Button,
      Checkbox,
    };
    
  • 要声明的冲洗,需要从components/DateSelect.jscomponents/Button.jscomponents/Checkbox.js

  • 导入内容
  • 转到这些文件并开始构建其中的内容
  • 一旦构建DateSelect,就会被告知从CheckBox
  • 导入components/index.js
  • 它已经知道components/index.js中的冲洗,所以它会在冲洗中寻找CheckBox(它'圈回'),但CheckBox尚未声明components/CheckBox.js但是,它返回undefined

这是时间问题。在我们尝试导入之后,只需点击几下就可以定义CheckBox,但是对于您的构建来说,点击几下就太晚了。

您可以通过立即记录CheckBox并在导入语句后几毫秒来显示...

// /components/DateSelect/DateSelect.js:

import { Checkbox } from '../';
console.log(CheckBox); // undefined
setTimeout(() => console.log(CheckBox), 4) // function CheckBox(_ref) { ...

因此,当您尝试声明MyCustomCheckbox时,CheckBox未定义。

在调用了DateSelect的render方法时,已声明CheckBox。相对而言,这比构建过程晚了。

这种问题没有100%安全的解决方案,因为它取决于您的应用程序结构整体。通常最好避免绕回同一模块

避免冲洗

您可以通过直接从components/CheckBox.js导入或者将索引模块方法更深一层并创建一个小的CheckBox模块来避免回到冲洗... ...

/components
  /CheckBox
    CheckBox.js
    index.js

...然后import {CheckBox} from '/components/Checkbox'