angular-cn/aio/content/guide/ts-to-js.md

44 KiB
Raw Blame History

@title 从 TypeScript 到 JavaScript

@intro 把 Angular 的 TypeScript 范例转换为 ES6 和 ES5 JavaScript.

@description

Anything you can do with Angular in TypeScript, you can also do in JavaScript. Translating from one language to the other is mostly a matter of changing the way you organize your code and access Angular APIs.

在 Angular 中,TypeScript 可以做的任何事,也可以用 JavaScript 实现。 将一种语言翻译成另一种语言,主要是改变了组织代码和访问 Angular API 的方式。

TypeScript is a popular language option for Angular development. Most code examples on the Internet as well as on this site are written in TypeScript. This cookbook contains recipes for translating TypeScript code examples to ES6 and to ES5 so that JavaScript developers can read and write Angular apps in their preferred dialect.

TypeScript 在 Angular 开发中比较流行。 互联网上和本网站中的大多数范例都是用 TypeScript 写的。

{@a toc}

Table of contents

目录

Run and compare the live TypeScript and JavaScript code shown in this cookbook.

运行在线例子,比较 TypeScript 版和 JavaScript 版的代码。

{@a from-ts}

TypeScript to ES6 to ES5

##TypeScriptES6ES5

TypeScript is a typed superset of ES6 JavaScript. ES6 JavaScript is a superset of ES5 JavaScript. ES5 is the kind of JavaScript that runs natively in all modern browsers. The transformation of TypeScript code all the way down to ES5 code can be seen as "shedding" features.

TypeScript ES6 JavaScript 类型化的超集ES6 JavaScriptES5 JavaScript 的超集。ES5 是可以在所有现代浏览器中运行的 JavaScript。

The downgrade progression is

降级的过程是

  • TypeScript to ES6-with-decorators

    TypeScript 降级到 带装饰器的 ES6

  • ES6-with-decorators to ES6-without-decorators ("plain ES6")

    带装饰器的 ES6 降级到 没有装饰器的 ES6 (“普通 ES6”)

  • ES6-without-decorators to ES5

    没有装饰器的 ES6 降级到 ES5

When translating from TypeScript to ES6-with-decorators, remove class property access modifiers such as public and private. Remove most of the type declarations, such as :string and :boolean but keep the constructor parameter types which are used for dependency injection.

TypeScript 翻译到 带装饰器的 ES6 时,移除了类属性访问修饰符,如publicprivate。 移除了大部分的类型声明,如:string:boolean。 但保留了用于依赖注入的构造函数参数类型

From ES6-with-decorators to plain ES6, remove all decorators and the remaining types. You must declare properties in the class constructor (this.title = '...') rather than in the body of the class.

带装饰器的 ES6 翻译到_普通 ES6_ 时,移除了所有的装饰器和剩下的类型。 必须在构造函数中声明属性(this.title = '...'),而不是在类的代码体中。

Finally, from plain ES6 to ES5, the main missing features are import statements and class declarations.

最后,普通 ES6 翻译成 ES5,缺少的主要特性是importclass声明。

For plain ES6 transpilation you can start with a setup similar to the TypeScript quickstart and adjust the application code accordingly. Transpile with Babel using the es2015 preset. To use decorators and annotations with Babel, install the angular2 preset as well.

对_普通 ES6_ 的翻译,可以从类似 TypeScript 快速开始的设置开始, 调整相应代码。然后用 Babel 进行转译,使用es2015预设值。 要在 Babel 中使用装饰器和注释,还需安装angular2预设值。

{@a modularity}

Importing and Exporting

导入和导出

Importing Angular Code

导入 Angular 代码

In both TypeScript and ES6, you import Angular classes, functions, and other members with ES6 import statements.

TypeScriptES6 中,可以使用 ES6 import语句导入 Angular 类、函数和其它成员。

In ES5, you access the Angular entities of the the Angular packages through the global ng object. Anything you can import from @angular is a nested member of this ng object:

ES5 中,通过全局ng对象访问 Angular 包中的 Angular 实体。 凡是可以从@angular导入的,都是该ng对象的嵌套成员。

Exporting Application Code

导出应用代码

Each file in a TypeScript or ES6 Angular application constitutes an ES6 module. When you want to make something available to other modules, you export it.

TypeScriptES6 Angular 应用中每个文件都构成一个 ES6 模块。 当想要让某个东西对其它模块可用时,就export它。

ES5 lacks native support for modules. In an Angular ES5 application, you load each file manually by adding a <script> tag to index.html.

ES5 不支持模块。在 Angular ES5 应用中,需要在index.html中添加<script>标签,手工加载每个文件。

The order of <script> tags is often significant. You must load a file that defines a public JavaScript entity before a file that references that entity.

<script>标签的顺序通常很重要。 必须在引用实体的文件之前,加载定义该公共 JavaScript 实体的文件。

The best practice in ES5 is to create a form of modularity that avoids polluting the global scope. Add one application namespace object such as app to the global document. Then each code file "exports" public entities by attaching them to that namespace object, e.g., app.HeroComponent. You could factor a large application into several sub-namespaces which leads to "exports" along the lines of app.heroQueries.HeroComponent.

ES5 中,最佳实践是,创建某种形式的模块化,避免污染全局作用域。 添加一个应用命名空间对象(如app)到全局的document。 接着,每个代码文件都通过附加到该命名空间来“导出”公共实体,例如,app.HeroComponent。 可以把一个大型应用中分解成多个子命名空间,可以象这样进行“导出”,app.heroQueries.HeroComponent

Every ES5 file should wrap code in an Immediately Invoked Function Expression (IIFE) to limit unintentional leaking of private symbols into the global scope.

每个 ES5 文件都应包裹在立即调用函数表达式 (IIFE) 中, 防止把私有符号无意地泄漏到全局作用域。

Here is a HeroComponent as it might be defined and "exported" in each of the four language variants.

下面是HeroComponent定义和“导出”的四种不同语言变种。

Importing Application Code

导入应用代码

In TypeScript and ES6 apps, you import things that have been exported from other modules.

TypeScriptES6 应用中,可以导入 (import) 其它模块已导出的东西。

In ES5 you use the shared namespace object to access "exported" entities from other files.

ES5 中,使用共享的命名空间对象访问其它文件“导出”的实体。

Alternatively, you can use a module loader such as Webpack or Browserify in an Angular JavaScript project. In such a project, you would use CommonJS modules and the require function to load Angular framework code. Then use module.exports and require to export and import application code.

还可以在 Angular JavaScript 项目中使用模块加载器,如 Webpack 或 Browserify。 在这样的项目中,使用 CommonJS 模块和require函数来加载 Angular 框架代码。 用module.exportsrequire导入和导出应用代码。

{@a class-metadata}

Classes and Class Metadata

类和类的元数据

Classes

Most Angular TypeScript and ES6 code is written as classes.

大多数 Angular TypeScriptES6 代码是写成了类。

Properties and method parameters of TypeScript classes may be marked with the access modifiers private, internal, and public. Remove these modifiers when translating to JavaScript.

TypeScript 类的属性和方法参数可以用访问修饰符privateinternalpublic标记。 当翻译成 JavaScript 时,移除这些修饰符。

Most type declarations (e.g, :string and :boolean) should be removed when translating to JavaScript. When translating to ES6-with-decorators, do not remove types from constructor parameters!

当翻译成 JavaScript 时,移除大多数类型声明(如,:string:boolean)。 当翻译成_带装饰器的 ES6_ 时,不移除构造函数参数类型!

Look for types in TypeScript property declarations. In general it is better to initialize such properties with default values because many browser JavaScript engines can generate more performant code. When TypeScript code follows this same advice, it can infer the property types and there is nothing to remove during translation.

看一下 TypeScript 属性声明中的类型。通常,最好用缺省值初始化这些属性,因为许多浏览器的 JavaScript 引擎可生成更高性能的代码。当 TypeScript 代码遵循这一建议时,它可以推导出属性类型,翻译时就不需要移除任何内容。

In ES6-without-decorators, properties of classes must be assigned inside the constructor.

在_不带装饰器的 ES6_ 中,类的属性必须在构造函数中指定。

ES5 JavaScript has no classes. Use the constructor function pattern instead, adding methods to the prototype.

ES5 JavaScript 没有类。 使用构造函数模式,把方法添加到 prototype 中。

Metadata

元数据

When writing in TypeScript or ES6-with-decorators, provide configuration and metadata by adorning a class with one or more decorators. For example, you supply metadata to a component class by preceding its definition with a @Component decorator function whose argument is an object literal with metadata properties.

当用 TypeScript带装饰器的 ES6 编写代码时,使用一个或多个装饰器 (decorator) 来修饰类, 提供配置和元数据。

In plain ES6, you provide metadata by attaching an annotations array to the class. Each item in the array is a new instance of a metadata decorator created with a similar metadata object literal.

在_普通 ES6_ 中通过向_类_附加一个annotations数组来提供元数据。

In ES5, you also provide an annotations array but you attach it to the constructor function rather than to a class.

在_ES5_中也是提供一个annotations数组但把它附加到_构造函数_而不是类。

See these variations side-by-side:

看一下这些变种:

External Template file

外部模块文件

A large component template is often kept in a separate template file.

大的组件模板通常是放在独立的文件中。

The component (HeroTitleComponent in this case) then references the template file in its metadata templateUrl property:

接着,组件(这里是HeroTitleComponent)在它的元数据templateUrl属性中引用该模板文件:

Note that both the TypeScript and ES6 templateUrl properties identify the location of the template file relative to the component module.

注意,TypeScript 和两个_ES6_的templateUrl属性_相对于组件模块_来标识模板文件的位置。

{@a dsl}

ES5 DSL

ES5 领域专用语言

This ES5 pattern of creating a constructor and annotating it with metadata is so common that Angular provides a convenience API to make it a little more compact and locates the metadata above the constructor, as you would if you wrote in TypeScript or ES6-with-decorators.

创建构造函数并用元数据对它进行注释,是一个常见的 ES5 模式Angular 提供了一套方便的 API使代码更简洁 并且元数据也刚好位于构造函数的上方,看起来就像 TypeScript带装饰器的 ES6 写的代码。

This API (Application Programming Interface) is commonly known as the ES5 DSL (Domain Specific Language).

这个 API (Application Programming Interface应用编程接口) 通常称作 ES5 DSL (Domain Specific Language领域专用语言)。

Set an application namespace property (e.g., app.HeroDslComponent) to the result of an ng.core.Component function call. Pass the same metadata object to ng.core.Component as you did before. Then chain a call to the Class method which takes an object defining the class constructor and instance methods.

ng.core.Component函数调用的结果设置到应用命名空间属性,如app.HeroDslComponent。 向ng.core.Component传递与之前一样的元数据对象。 接着,在调用链上调用Class函数,它接收一个对象,其中定义了类的构造函数和实例方法。

Here is an example of the HeroComponent, re-written with the DSL, next to the original ES5 version for comparison:

下例中的HeroComponent,用 DSL 进行了重写,跟原来的 ES5 版本进行对比一下:

Name the constructor 命名构造函数

A named constructor displays clearly in the console log if the component throws a runtime error. An unnamed constructor displays as an anonymous function (e.g., class0) which is impossible to find in the source code.

如果组件抛出运行时异常,命名的构造函数在控制台日志中显示得更清楚。 未命名的构造函数显示为匿名函数(如,class0),不可能在源代码中找到它。

Properties with getters and setters

具有 getter 和 setter 的属性

TypeScript and ES6 support with getters and setters. Here's an example of a read-only TypeScript property with a getter that prepares a toggle-button label for the next clicked state:

TypeScriptES6 支持 getter 和 setter。 下面是 TypeScript 只读属性的例子,它有一个 getter为下一次点击状态准备切换按钮的标签

This TypeScript "getter" property is transpiled to an ES5 defined property. The ES5 DSL does not support defined properties directly but you can still create them by extracting the "class" prototype and adding the defined property in raw JavaScript like this:

这个 TypeScript "getter" 属性会翻译成 ES5 已定义属性ES5 DSL 不直接支持_已定义属性_你仍可提取“类”原型象下面这样添加_已定义属性_

DSL for other classes

用于其它类的 DSL

There are similar DSLs for other decorated classes. You can define a directive with ng.core.Directive:

其它被装饰的类也有类似的DSL可以用ng.core.Directive定义指令:

app.MyDirective = ng.core.Directive({ selector: '[myDirective]' }).Class({ ... });

and a pipe with ng.core.Pipe:

ng.core.Pipe添加一个管道:

app.MyPipe = ng.core.Pipe({ name: 'myPipe' }).Class({ ... });

{@a interfaces}

Interfaces

接口

A TypeScript interface helps ensure that a class implements the interface's members correctly. We strongly recommend Angular interfaces where appropriate. For example, the component class that implements the ngOnInit lifecycle hook method should implement the OnInit interface.

_TypeScript_用于确保一个类正确地实现了接口成员。 在适当的地方,我们强烈推荐使用 Angular 接口。 例如,实现了ngOnInit生命周期钩子方法的组件类应实现OnInit接口。

TypeScript interfaces exist for developer convenience and are not used by Angular at runtime. They have no physical manifestation in the generated JavaScript code. Just implement the methods and ignore interfaces when translating code samples from TypeScript to JavaScript.

TypeScript 接口只是为了方便开发人员Angular 在运行时并不使用它。 它们在生成的 JavaScript中并不存在。 当从 TypeScript 翻译成 JavaScript 时,只保留了实现方法,而忽略接口。

{@a io-decorators}

Input and Output Metadata

输入和输出元数据

Input and Output Decorators

输入和输出装饰器

In TypeScript and ES6-with-decorators, you often add metadata to class properties with property decorators. For example, you apply @Input and @Output property decorators to public class properties that will be the target of data binding expressions in parent components.

TypeScript带装饰器的 ES6经常会用_属性装饰器_往类的_属性_上添加元数据。 例如,向公共类属性添加@Input@Output属性装饰器 会使这些属性成为父组件绑定表达式的目标。

There is no equivalent of a property decorator in ES5 or plain ES6. Fortunately, every property decorator has an equivalent representation in a class decorator metadata property. A TypeScript @Input property decorator can be represented by an item in the Component metadata's inputs array.

ES5普通 ES6 中,没有等价的属性装饰器。 幸运的是,每个属性装饰器在类的装饰器元数据属性中有等价的表示形式。 TypeScript@Input属性装饰器可以表示为Component元数据的inputs数组中的一项。

You already know how to add Component or Directive class metadata in any JavaScript dialect so there's nothing fundamentally new about adding another property. But note that what would have been separate @Input and @Output property decorators for each class property are combined in the metadata inputs and outputs arrays.

你已经知道如何用_任意的_ JavaScript 方言添加ComponentDirective元数据, 所以添加另一个属性也没什么新鲜的。 但要注意的是用于每个类属性的那些_分离_的@Input@Output属性装饰器,都合并到了inputsoutputs_数组_中。

In the previous example, one of the public-facing binding names (cancelMsg) differs from the corresponding class property name (notOkMsg). That's OK but you must tell Angular about it so that it can map an external binding of cancelMsg to the component's notOkMsg property.

上例中,其中一个面向公共的绑定名 (cancelMsg),不同于相应的类属性名 (notOkMsg)。 这样做没有问题,但必须把它告诉 Angular这样 Angular 才能把cancelMsg的外部绑定映射到组件的notOkMsg属性。

In TypeScript and ES6-with-decorators, you specify the special binding name in the argument to the property decorator.

TypeScript带装饰器的 ES6 中,在属性装饰器的参数中指定特定的绑定名。

In ES5 and plain ES6 code, convey this pairing with the propertyName: bindingName syntax in the class metadata.

ES5普通 ES6 中,用propertyName: bindingName语法表示在类的元数据中。

Dependency Injection

依赖注入

Angular relies heavily on Dependency Injection to provide services to the objects it creates. When Angular creates a new component, directive, pipe or another service, it sets the class constructor parameters to instances of services provided by an Injector.

Angular 严重依赖依赖注入来为它创建的对象提供服务。 当 Angular 创建一个新组件、指令、管道或其它服务时, 它把_注入器_提供的服务的实例传递给类的构造函数参数。

The developer must tell Angular what to inject into each parameter.

开发人员必须告诉 Angular 向每个参数中注入什么。

Injection by Class Type

按类的类型注入

The easiest and most popular technique in TypeScript and ES6-with-decorators is to set the constructor parameter type to the class associated with the service to inject.

TypeScript带装饰器的 ES6 中,最简单和流行的技术是把构造函数参数的类型设置为待注入服务的类。

The TypeScript transpiler writes parameter type information into the generated JavaScript. Angular reads that information at runtime and locates the corresponding service in the appropriate Injector.. The ES6-with-decorators transpiler does essentially the same thing using the same parameter-typing syntax.

TypeScript 转译器把参数类型信息写进生成的 JavaScript。 Angular 在运行时读取该信息并在适当的_注入器_中定位相应的服务。 带装饰器的 ES6 转译器本质上也使用同样的参数类型语法,做同样的工作。

ES5 and plain ES6 lack types so you must identify "injectables" by attaching a parameters array to the constructor function. Each item in the array specifies the service's injection token.

ES5普通 ES6 缺少类型,必须向构造函数附加**parameters**数组来标识“可注入对象”。 数组中的每一项指定一个服务的注入令牌。

As with TypeScript the most popular token is a class, or rather a constructor function that represents a class in ES5 and plain ES6. The format of the parameters array varies:

TypeScript最常用的令牌是类而_ES5_ 和 普通 ES6 使用_构造函数_表示一个类。 因此,parameters数组会有所不同:

  • plain ES6 — nest each constructor function in a sub-array.

    普通 ES6 — 函数构造嵌套在一个子数组中。

  • ES5 — simply list the constructor functions.

    ES5 — 简单列出构造函数。

When writing with ES5 DSL, set the Class.constructor property to an array whose first parameters are the injectable constructor functions and whose last parameter is the class constructor itself. This format should be familiar to AngularJS developers.

当用 ES5 DSL 时,把Class.constructor属性设置为一个数组,它的前面的参数是 注入的服务,最后一个参数是类构造函数本身。 AngularJS 的开发人员对这种形式应该很熟悉。

Injection with the @Inject decorator

用 @Inject 装饰器注入

Sometimes the dependency injection token isn't a class or constructor function.

有时,依赖注入的令牌不是类或构造函数。

In TypeScript and ES6-with-decorators, you precede the class constructor parameter by calling the @Inject() decorator with the injection token. In the following example, the token is the string 'heroName'.

TypeScript带装饰器的 ES6 中,可以在类的构造函数参数前调用@Inject()装饰器来指定注入令牌。 在这个例子中,这个令牌是字符串'heroName'

The other JavaScript dialects add a parameters array to the class contructor function. Each item constains a new instance of Inject:

其它 JavaScript 方言是通过向类的构造函数添加parameters数组。 其中的每一项是Inject的实例。

  • plain ES6 — each item is a new instance of Inject(token) in a sub-array.

    普通 ES6 — 每一项是嵌套在一个子数组中的Inject(token)的实例。

  • ES5 — simply list the string tokens.

    ES5 — 简单列出字符串令牌。

When writing with ES5 DSL, set the Class.constructor property to a function definition array as before. Create a new instance of ng.core.Inject(token) for each parameter.

当用 ES5 DSL 时,象前面那样把Class.constructor属性设置为函数定义数组。 为每个参数创建一个ng.core.Inject(token)

Additional Injection Decorators

其它注入装饰器

You can qualify injection behavior with injection decorators from @angular/core.

可以使用@angular/core中的注入装饰器来限定注入行为。

In TypeScript and ES6-with-decorators, you precede the constructor parameters with injection qualifiers such as:

TypeScript带装饰器的 ES6 中,可以将下列注入限定符加在构造函数参数前面:

  • @Optional sets the parameter to null if the service is missing

    @Optional 如果找不到服务,设置参数为null

  • @Attribute to inject a host element attribute value

    @Attribute 注入宿主元素属性值

  • @ContentChild to inject a content child

    @ContentChild 注入内容子组件

  • @ViewChild to inject a view child

    @ViewChild 注入视图子组件

  • @Host to inject a service in this component or its host

    @Host 注入本组件或它宿主中的服务

  • @SkipSelf to inject a service provided in an ancestor of this component

    @SkipSelf 注入本组件祖先中提供的服务

In plain ES6 and ES5, create an instance of the equivalent injection qualifier in a nested array within the parameters array. For example, you'd write new Optional() in plain ES6 and new ng.core.Optional() in ES5.

在_ES5_ 或 普通 ES6 中,通过在parameters数组中创建一个嵌套数组,创建等价的注入限定符实例。

When writing with ES5 DSL, set the Class.constructor property to a function definition array as before. Use a nested array to define a parameter's complete injection specification.

当用 ES5 DSL 时,象前面那样把Class.constructor属性设置为函数定义数组。 用嵌套数组来定义参数完整的注入规格说明。

In the example above, there is no provider for the 'titlePrefix' token. Without Optional, Angular would raise an error. With Optional, Angular sets the constructor parameter to null and the component displays the title without a prefix.

上例中,'titlePrefix'令牌没有提供商。 如果没有OptionalAngular 将抛出错误。 加上OptionalAngular 将构造函数参数设置为null 组件显示没有前缀的标题。

{@a host-binding}

Host Binding

宿主绑定

Angular supports bindings to properties and events of the host element which is the element whose tag matches the component selector.

Angular 支持绑定到_宿主元素_的属性和事件 宿主元素是那些标签匹配组件选择器的元素。

Host Decorators

宿主装饰器

In TypeScript and ES6-with-decorators, you can use host property decorators to bind a host element to a component or directive. The @HostBinding decorator binds host element properties to component data properties. The @HostListener decorator binds host element events to component event handlers.

TypeScript带装饰器的 ES6 中,可以使用宿主属性装饰器把宿主元素绑定到组件或指令。 @HostBinding装饰器把宿主元素属性绑定到组件数据属性。 @HostListener装饰器把宿主元素事件绑定到组件事件处理器。

In plain ES6 or ES5, add a host attribute to the component metadata to achieve the same effect as @HostBinding and @HostListener.

在_ES5_ 或 普通 ES6 中,向组件元数据添加host属性可以获得同样的效果。

The host value is an object whose properties are host property and listener bindings:

host的值是一个对象,它的属性是宿主属性和监听器绑定:

  • Each key follows regular Angular binding syntax: [property] for host bindings or (event) for host listeners.

    每个键遵循 Angular 绑定语法:[property]用于宿主绑定,(event)用于宿主监听器。

  • Each value identifies the corresponding component property or method.

    每个值标识相应的组件属性或方法。

Host Metadata

宿主元数据

Some developers prefer to specify host properties and listeners in the component metadata. They'd rather do it the way you must do it ES5 and plain ES6.

一些开发人员更喜欢在组件元数据中指定宿主属性和监听器。 它们宁愿采用这种方式,也是 ES5普通 ES6 中必须采用的方式。

The following re-implementation of the HeroComponent reminds us that any property metadata decorator can be expressed as component or directive metadata in both TypeScript and ES6-with-decorators. These particular TypeScript and ES6 code snippets happen to be identical.

下面重新实现了HeroComponent,它提醒我们,在 TypeScript带装饰器的 ES6 中, _任何属性元数据装饰器_都可以表示为组件或指令元数据。

{@a view-child-decorators}

View and Child Decorators

视图和子组件装饰器

Several property decorators query a component's nested view and content components.

有几个_属性_装饰器可用于查询组件的嵌套视图和内容组件。

View children are associated with element tags that appear within the component's template.

_视图_子组件与出现在组件模板_内_的元素标签相关联。

Content children are associated with elements that appear between the component's element tags; they are projected into an <ng-content> slot in the component's template.

_内容_子组件与出现在组件元素标签_之间_的那些元素相关联 它们被投影到组件模板的<ng-content>中。

The @ViewChild and @ViewChildren property decorators allow a component to query instances of other components that are used in its view.

@ViewChild@ViewChildren 属性装饰器允许组件查询位于其视图中的其它组件的实例。

In ES5 and ES6, you access a component's view children by adding a queries property to the component metadata. The queries property value is a hash map.

ES5ES6 中,通过向组件元数据添加queries属性来访问组件的视图子组件。 queries属性是一个映射表。

  • each key is the name of a component property that will hold the view child or children.

    每个_键_是用来保存视图子组件的组件属性名。

  • each value is a new instance of either ViewChild or ViewChildren.

    每个_值_是ViewChildViewChildren的实例。

The @ContentChild and @ContentChildren property decorators allow a component to query instances of other components that have been projected into its view from elsewhere.

@ContentChild@ContentChildren 装饰器允许组件查询从其它地方投影到视图里的其它组件的实例。

They can be added in the same way as @ViewChild and @ViewChildren.

添加它们的方式与@ViewChild@ViewChildren 相同。

In TypeScript and ES6-with-decorators you can also use the queries metadata instead of the @ViewChild and @ContentChild property decorators.

TypeScript带装饰器的 ES6 中,还可以使用queries元数据代替 @ViewChild@ContentChild属性装饰器。

{@a aot}

AOT Compilation in TypeScript only

只用于 TypeScript 的预编译

Angular offers two modes of template compilation, JIT (Just-in-Time) and AOT (Ahead-of-Time). Currently the AOT compiler only works with TypeScript applications because, in part, it generates TypeScript files as an intermediate result. AOT is not an option for pure JavaScript applications at this time.

Angular 模板编译有两种方式JiT (Just-in-Time即时编译) 和 AoT (Ahead-of-Time预编译)。 目前,预编译只能用于 TypeScript 应用,因为(部分原因)它生成的中间结果是 TypeScript 文件。 当前,预编译不能用于纯 JavaScript 应用