在一个地方导入模块以更好地组织并删除重复的导入语句

Import modules in one place for better organisation and remove duplicate import statements

我有以下目录结构

app
├── default.js
├── index.html
├── ObserverPattern
    ├── ConcreteObserver.mjs
    ├── ConcreteSubject.mjs
    ├── ObserverList.mjs
    ├── Observer.mjs
    └── Subject.mjs

index.html 我有 <script type="module" src="default.js"></script>

default.js中我有以下代码

import { Observer } from "./ObserverPattern/Observer.mjs";
import { ObserverList } from "./ObserverPattern/ObserverList.mjs";
import { Subject } from "./ObserverPattern/Subject.mjs";
import { ConcreteObserver } from "./ObserverPattern/ConcreteObserver.mjs";
import { ConcreteSubject } from "./ObserverPattern/ConcreteSubject.mjs";

ConcreteObserver.mjs中我有以下代码

class ConcreteObserver extends Observer {
  constructor(element) {
    super();
    this.element = element;
  }

  update(value) {
    this.element.checked = value;
  }

}

export {
  ConcreteObserver
};

当我 运行 通过本地网络服务器时,我收到错误 Uncaught ReferenceError: Observer is not defined

如果我然后在 ConcreteObserver.mjs 的顶部添加 import { Observer } from './Observer.mjs'; 那么它可以正常工作。

有没有办法导入 default.js 中的所有模块,这样我就不必在每个具体实现中都包含 import { Observer } from './Observer.mjs';

类似于 php 作曲家 autoload

谢谢

模块的很大一部分意义在于隔离代码,这样您就不会得到大量未使用的 in-scope 变量。

由于您似乎 运行 在浏览器中,您 可以 显式地为全局对象赋值…

import { Observer } from "./ObserverPattern/Observer.mjs";
window.Observer = Observer;

然后在别处使用window.Observer

但这使得代码难以管理。如果您未能正确分配变量,Linters 将无法捕获错误。在分配给 window 对象之前尝试读取值的竞争条件存在风险。

如果你需要使用Observer然后在你需要使用它的地方导入它。

模块的一个要点是它们是 self-contained 并且它们之间的关系是显式的、静态定义的(主要是;有动态导入形式)。 ESM 中没有自动导入。

要让您的 ConcreteObserver 实现工作 as-is,Observer 必须是全局的,并且必须在评估 ConcreteObserver 之前定义。这是你可以做的事情,尽管我认为你不应该这样做,方法是让 Observer.mjsObserver 分配给 globalThis 上的 属性(在现代环境中,global 在旧版浏览器中 Node.js 或 window)。但除此之外,您至少需要一个 import in ConcreteObserver.mjs.

如果这是一个目标,您可以采取一些措施来减少不同 import 语句的数量。例如,您可以将事物更多地组合在一起(ObserverObserverListSubject 看起来都是 closely-related,因此它们可能都放在一个模块中)。但是您仍然需要 ConcreteObserver.mjs 中的 import。一个模块也可以从其他模块 re-export 获取东西(例如:export { Something } from "./somewhere.mjs";),如果你想为所有 ObserverPattern 东西创建一个主模块,导出在构成它的文件。但是同样,您仍然需要 import in ConcreteObserver.mjs