译文 | Angular中的AoT编译( 四 )


// component.ts@Component({selector: 'third-party',template: `{{ _initials }}`})class ThirdPartyComponent {private _initials: string;private _name: string;@Input()set name(name: string) {if (name) {this._initials = name.split(' ').map(n => n[0]).join('. ') + '.';this._name = name;}}}
这个组件有一个属性 name , 它只能写入而无法读取 。在 name 属性的方法中 , 计算了属性的值 。
我们可以用类似下面的方式使用这个组件:
@Component({template: ''// ...})// ...
在JiT编译模式下 , 一切正常 , 因为JiT模式只生成代码 。每次 name 属性的值发生变化 ,  就会被重新计算 。但是 , 这个组件却不是AoT友好的 , 必须改为:
// component.ts@Component({selector: 'third-party',template: `{{ initials }}`})class ThirdPartyComponent {initials: string;private _name: string;@Input()set name(name: string) {...}}
这个工具可以确保你在模板中每次都能访问到成员 。
这让组件的使用者可以这样做:
import {ThirdPartyComponent} from 'third-party-lib';@Component({template: ''// ...})class Consumer {@ViewChild(ThirdPartyComponent) cmp: ThirdPartyComponent;name = 'Foo Bar';ngAfterViewInit() {this.cmp.initials = 'M. D.';}}
对属性的直接修改导致了组件处于不一致性的状态:组件的 _name 的值是 Foo Bar , 但是它的的值是 M. D. , 而非 F. B. 。

译文 | Angular中的AoT编译

文章插图
在的源码中 , 我们可以找到解决的办法 , 使用的 /** @ */ 注释声明 , 就能够达到既保证组件代码对AoT友好 , 又能够确保组件的封装良好的目的 。
// component.ts@Component({selector: 'third-party',template: `{{ initials }}`})class ThirdPartyComponent {/** @internal */initials: string;private _name: string;@Input()set name(name: string) {...}}
属性仍然是的 。我们在使用 tsc 编译这个组件时 , 设置 -- 和 -- 参数 ,  属性就会从组件的类型定义文件(即 .d.ts 文件)中被删掉 。这样我们就可以做到在我们的类库内部使用它 , 但是我们的组件使用者无法使用它 。
.ts 概要
我们来对幕后所发生的一切做一些概要描述 。拿我们前面的例子中的为例 , 编译器会生成两个类:
负责渲染这个组件的模板 , 以及进行变化检测 。在执行变化检测时 , 它会对 this..hero.name之前保存的值和当前值做比较 , 一旦发现这两个值不一致 ,  元素就会被更新 , 这意味着我们必须保持 this..hero 和 hero.name 是的 。这一点可以通过这个工具来辅助确保 。