13

我正在使用带有 Typescript 的 Angular2

假设我的应用组件模板中有以下内容:

... 
<coffee-cup [coffee]=""
...

我的coffee-cup组件:

@Component({
  selector: 'coffee-cup',
  ...
})
export class CoffeeCup {

  @Input() 
  public coffee = 0;

}

我目前不确定我的输入应该是什么样子。它可能看起来像这样:

@Input()
public coffee = 0;

或者

@Input()
private coffee = 0;

我目前倾向于将成员变量咖啡设为私有。

  • 我想为组件定义一个清晰的公共 API
  • 我只想公开通过模板设置咖啡属性
  • 我目前没有任何理由允许直接从父组件读取或设置咖啡。如果需要,我可以删除 private 修饰符。

我查看组件的方式是有两个单独的 API 可以与之交互:

  1. 模板 API,由@Inputs@Outputs
  2. 由所有公共属性和方法组成的 Typescript API

我没有检查以下情况会发生什么,但是,它可能会改变答案:

  • 假设咖啡会员是公开的。如果我appComponent可以CoffeeCup使用@ViewChild并设置咖啡成员,生命周期钩子(如ngOnChange)会触发吗?

重申这个问题:Angular2 应该@Input是公开的还是我们可以/应该通过将它们设为私有来拥有更严格的 API?

4

1 回答 1

18

首先,从 API 设计的角度来看,@Input意味着公开。从角度来看也是如此,这些装饰器描述了与组件交互的接口。

Angular使用@Input装饰器或任何其他元装饰器以让 Angular 了解您的意图并更好地理解模板及其与组件类的关系。

在某些情况下,变更检测引擎也使用它。例如,@Input更改检测跟踪的字段,它向 CD 引擎提示应该监视此属性。

拥有一个带有@Input装饰器的私有属性在运行时不应该有任何影响。这个修饰符是虚拟的,它在 TypeScript 到 JavaScript 编译之后消失了。

但是,根据您的环境,可能会出现一些影响:

一般来说,拥有 TypeScript 和元数据的一大好处是拥有一个智能 IDE,这意味着 IDE 可以在您编码时为您提供帮助。根据每个 IDE 的实现,拥有私有属性可能会或可能不会影响。@Input当您为该组件编写 HTML 标记时,拥有一个属性将导致 IDE 在智能感知窗口上向您显示该属性。

另一个风险因素是未来对打字稿中的缩小/丑化的支持。顾名思义,私有属性在类内部没有其他地方使用。这个特性意味着编译器可以更改私有属性的名称,以便它们占用更少的字节,这也使它们“更加私有”,因为标识符可能会在构建之间发生变化。例如:private mySpecialProperty: string在缩小之后p1,编译器会将类中对该标识符的所有引用更改为 match p1。因此,今天拥有它会起作用,但将来它可能会限制构建功能。

要考虑的另一点是,虽然 Angular 不关心您的编译器所做的修饰符,但动态组件的创建将受到限制。换句话说,在 html 标记中创建组件将没有任何问题,但使用 html 动态创建组件ComponentResolver -> ComponentFactor将受到限制,因为您将无法使用代码将这些输入分配给组件的实例。如果你不打算这样做,那很好。

如果您正在构建供他人使用的组件,则public修饰符对于@Input/@Output. 您组件的用户应该能够动态创建您的组件。

这也回答了有关在父/子组件上访问这些属性以获取对咖啡组件的引用的问题。只能通过模板标记进行绑定。例如,您将无法手动注册到EventEmitter咖啡组件上注册的 s。这有时是必需的,请参阅场景作为示例。

至于生命周期钩子,它不应该有任何影响,因为 angular 不检查类型而是检查存在性。

因此,总而言之,在大多数用例中,您不应该有任何问题,但随着您的应用程序的进展,您可能会解决一些问题,或者不解决。您将来可能还必须选择退出高级缩小功能......

于 2016-07-19T22:33:29.160 回答