首页 > 解决方案 > ES2015 模块,我应该导入/导出所有内容吗?

问题描述

我最近开始在javascript中使用导入导出,但我有点困惑。我不确定我应该导出什么,以及我应该在文件中保留什么。我不知道如何用英语表达这很好,所以这是我的代码中的一小部分:

/client/js/Inventory.js文件,模块:

import {
  $,
  renderHTML,
  game
} from "../main.js";

const template = {
  titanium: {
    name: "Titanium",
    description: "Description here..."
  }
}

export default class Inventory {
  constructor(inventory) {
    this._name = inventory.name;
    this._description = inventory.description;
  }

  get name() {return this._name}
  get description() {return this._description}

  generate(id) {
    renderHTML("inventory, `
      <div class="inventory" id="${id}">
        content here...
      </div>
    `);
  }

  static make(id) {
    game.inventory[id] = new Inventory(template[id]);
    game.inventory[id].generate(id);
}

我的/client/main.js文件看起来像这样:

import Inventory from "./js/Inventory.js";

const $ = (id) => document.getElementById(id);
const renderHTML = (id, str) => $(id).insertAdjacentHTML("beforeend", str);

const game = {
  inventory: {}
};

Inventory.make("titanium");

export {
  $,
  renderHTML,
  game
};

由于我是gamemain.js文件中导出对象,这是否意味着在Inventory.jsgame文件导入后正在创建一个新对象,或者这是否意味着Inventory.js文件现在可以访问main.js文件的对象?game

由于我在main.js文件中调用类,是否还需要从Inventory.jstemplate文件中导出对象,并将其导入到main.js文件中?

只导出类工作得很好,但我不明白main.js是如何访问模板的,如果它没有被导出?如果在main.js中没有找到,它会在Inventory.js文件中查找吗?

谢谢!

标签: javascriptclassimportecmascript-6export

解决方案


这很简单。模块是一种在不同代码段之间共享代码或数据的结构化方式。

导出希望与将加载您的模块的其他模块共享的任何功能或数据。

如果您无意分享或不需要分享,请勿导出。如果您确实需要共享它或某些其他模块需要能够访问它,您可以导出它。导出是与其他模块共享的手段。

您从需要在此模块中使用的其他模块导入任何属性。

对于导入,您只需导入您现在需要的内容。无需导入您将来“可能”需要的东西。您始终可以在实际需要时添加导入。

对于导出,您只导出您现在打算共享的内容。如果您以后发现需要分享更多内容,您可以随时添加另一个导出。


仅在此模块中使用的代码不需要导出。实际上,模块的好处之一是您可以维护模块中的代码隐私或保护,因为其他代码无法访问模块中未通过导出以某种方式导出或共享的任何内容。


您可以在逻辑上将导出视为模块的“api”。这是其他模块可以在您的模块中调用的内容。

您可以在逻辑上将导入视为指定要从其他模块使用的“api”。

当一切都在全局命名空间中时(与原始浏览器设计一样),则没有显式导出或导入。在顶层声明的所有内容都是公开和共享的。这导致了各种各样的问题,特别是随着项目变得越来越大,文件越来越多,然后当你开始尝试使用第三方代码时变得更加复杂。

模块系统是一种结构化的方式,默认情况下,一切都是私有的。然后,您仅显式导出您想要共享的内容。然后,当有人想要使用您的 api 时,他们会显式导入他们想要使用的 api。每个模块都存在于自己的范围内,因此有自己的命名空间。模块也是一个非常自然的可测试单元。

在 Javascript 模块标准化之前,开发人员已经建立了一大堆不同的约定来尝试解决 Javascript 中的大型扁平全局命名空间。如果您使用 3rd 方库,在同一个项目中遇到多个约定并不少见。对于不尝试使用约定来解决这个问题的开发人员,代码可能会变得非常混乱,有很多潜在的变量命名冲突、函数的意外替换以及文件之间通常未记录的依赖关系网络等……标准化模块设计试图提供一种解决这些问题的通用方法,并且在此过程中,还可以更轻松地编写可重用、可测试、可共享的代码。


由于我是从 main.js 文件中导出游戏对象,这是否意味着在 Inventory.js 文件导入后正在创建一个新游戏对象,或者这是否意味着 Inventory.js 文件现在可以访问 main.js文件的游戏对象?

这意味着 Inventory.js 现在可以导出gamemain.js. 导出或导入时没有隐式复制。

由于我在 main.js 文件中调用类,是否还需要从 Inventory.js 文件中导出模板对象,并将其导入到 main.js 文件中?

您只需要从中导出inventory.js直接需要从其他文件中引用的内容。由于main.js不需要引用template变量目录,所以不需要导出它。inventory.js从加载和运行该模块导入的行为。这使得该template变量可用于inventory.js您的代码所需的所有代码。所以,不需要导出它。

只导出类工作得很好,但我不明白 main.js 是如何访问模板的,如果它没有被导出?如果在 main.js 中没有找到,它会在 Inventory.js 文件中查找吗?

导出Inventory类允许任何其他模块使用该类及其所有方法。导入任何内容的过程inventory.js会导致模块本身被加载,因此其中定义的所有变量inventory.jsinventory.js. 当您通过导出的类创建Inventory对象时,您正在运行inventory.js可以访问该模块中所有数据的代码。

作为2段进口的东西。首先加载引用的模块(如果尚未加载)。然后,获取您请求导入的导出。


推荐阅读