【问题标题】:How to export a TypeScript class in a way that won't disrupt accessing the object using plain old vanilla JavaScript如何以一种不会中断使用普通旧版 JavaScript 访问对象的方式导出 TypeScript 类
【发布时间】:2018-04-28 13:44:04
【问题描述】:

请原谅我对此的无知,我被困住了,希望得到一些指导。

以 TypeScript 的 playground page 上的 Greeter 类示例为例:

class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}

我的任务是构建和管理一个组件,该组件既可以在纯 HTML + JavaScript 环境中使用,也可以在 Angular 应用程序中使用。我正在使用 TypeScript 管理/编写此代码,并使用 TypeScript 将输出编译为 JavaScript。

回到上面的例子,如果我想在 Angular 中使该类可用(作为导入),我需要导出该类吗?

export class Greeter {
    ...
}

当我这样做时,页面会抛出错误:

Uncaught ReferenceError: define is not defined

编译后的 JavaScript 如下所示:

define(["require", "exports"], function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var Greeter = /** @class */ (function () {
        function Greeter(message) {
            this.greeting = message;
        }
        Greeter.prototype.greet = function () {
            return "Hello, " + this.greeting;
        };
        return Greeter;
    }());
    exports.Greeter = Greeter;
    var greeter = new Greeter("world");
});

因为 Greeter 类现在绑定到该定义块,我显然不能像这样实例化一个新类:

let greeter = new Greeter("world"); // < -- Won't work.

抛出错误:

Uncaught ReferenceError: Greeter is not defined

  1. 我将如何导出该类,以一种不会中断以普通 JavaScript 方式访问对象的方式?
  2. 我正在尝试做的事情可能吗?
  3. 这是一个合理的目标,还是我完全走错了路?

【问题讨论】:

  • define 出现在 Playground 中,因为它默认为 AMD 模块。这在实际代码中不会如此,并且取决于 module 编译器选项设置的内容。与 Angular 相关联的代码究竟如何?首先是 Angular 还是 AngularJS?你在 Angular 项目源文件中使用这个文件吗?在这种情况下,它将被编译为其他文件。是否将其导出为 NPM 包?
  • 它是 Angular,而不是 AngularJS。至于在 Angular 中使用它,还没有完全实现,但我的想法是,是的,我想导入该文件,然后将其定义为一个组件。目前,不是 NPM 包,但同样的想法也适用,在根应用程序的某处包含一个通用 JS 包,引用它或导入它并在应用程序中使用它。
  • 这是从头开始设置 Angular 应用程序时必须解决的众多问题之一。根据经验,Angular 应用程序使用 Angular CLI 进行脚手架和构建。它已经为您配置了 TS。另一种方法是使用样板项目,它已经为您配置了 TS。出于实际目的,您可以坚持使用它们并从那里的工作方式中学习。你可以向官方Angular plunk学习,其中当然包含TS配置,plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5

标签: javascript angular typescript


【解决方案1】:

好问题,你问的绝对有道理。

首先值得一提的是,您所说的“vanilla JavaScript”是具有 AMD 模块库兼容性的 ES5。 ES6 为 JavaScript 引入了原生语言级别的模块,这就是 exportimport 的语法。

TypeScript 有一个 compiler option --module,它允许您选择要编译的模块目标并为其生成输出。然而,对于外部模块系统,如AMDCommonJS,它实际上并不输出使其工作所需的模块系统,它只是发出与这些系统兼容的 JavaScript。由你决定是否包含模块系统,例如RequireJS,或者在内置支持的环境中运行,例如 NodeJS 的 CommonJS 模块系统。如果您将--module 目标设置为es6,您将看到它保留了export 语句,这将在支持ES6 模块的浏览器中工作(假设导入路径解析为浏览器可以访问的文件)。

另外值得一提的是,使用 Webpack 或 Browserify 等 JavaScript 捆绑器,您几乎可以从 TypeScript 获取任何模块输出并将其捆绑到浏览器中,而无需自己引入模块运行时,因为捆绑器会处理它。

希望对您有所帮助。

【讨论】:

  • 感谢@Aaron,感谢您的反馈!超级有帮助。将考虑所有这些点并相应地重构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-27
  • 1970-01-01
  • 2011-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多