Angular2 @Inputs 应该是公开的,还是我们可以/应该通过将它们设为私有来拥有更严格的 API? [英] Should Angular2 @Inputs be public or can/should we have a stricter API by making them private?

查看:20
本文介绍了Angular2 @Inputs 应该是公开的,还是我们可以/应该通过将它们设为私有来拥有更严格的 API?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用带有 Typescript 的 Angular2

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

<预><代码>...<coffee-cup [咖啡]=""...

我的 coffee-cup 组件:

@Component({选择器:'咖啡杯',...})出口类 CoffeeCup {@输入()公共咖啡 = 0;}

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

@Input()公共咖啡 = 0;

@Input()私人咖啡 = 0;

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

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

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

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

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

  • 假设 coffee 成员是 public.如果我的 appComponent 使用 @ViewChild 访问 CoffeeCup 并设置了 coffee 成员,生命周期挂钩(如 ngOnChange>) 火?

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

解决方案

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

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

在某些情况下,变更检测引擎也会使用它.例如,@Input 是一个变化检测跟踪的字段,它提示 CD 引擎应该监控这个属性.

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

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

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

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

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

<块引用>

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

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

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

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

I am using Angular2 with Typescript

Suppose I have the following in my app component's template:

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

My coffee-cup component:

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

  @Input() 
  public coffee = 0;

}

I am currently unsure of what my Input should look like. It could look like this:

@Input()
public coffee = 0;

Or

@Input()
private coffee = 0;

I am currently leaning towards making the member variable coffee private.

  • I want to define a clear public API for the component
  • I only want to expose setting the coffee property through the template
  • I don't presently have any reason to allow coffee to be read or set directly from the parent component. If the need arises, I can drop the private modifier.

The way that I am viewing a component is that there are two separate APIs to interact with it:

  1. The template API, which consists of the @Inputs and @Outputs
  2. The Typescript API which consists of all of the public properties and methods

I haven't checked what occurs in the following situation, however, it may change the answer:

  • Suppose the coffee member is public. If my appComponent gets access to CoffeeCup using @ViewChild and sets the coffee member, will the lifecycle hooks (like ngOnChange) fire?

To restate the question: Should Angular2 @Inputs be public or can/should we have a stricter API by making them private?

解决方案

First, from an API design perspective @Input implies public. This is also true from angular perspective, these decorators describes the interface to interact with a component.

The @Input decorator, or any other meta decorator is used by angular in a way of letting angular know about your intent and have better understanding of the template and it's relations with the component class.

It's also used, in some cases, by the change detection engine. For example, @Input is a field tracked by the change detection, it hints to the CD engine that this property should be monitored.

Having a private property with an @Input decorator shouldn't have any effect in runtime. This modifier is virtual and it's gone after TypeScript to JavaScript compilation.

However, there are some effects that might occur depending on your environment:

A great benefit of having TypeScript and metadata in general is having a smart IDE which means that the IDE can help you while you code. Having a private property might or might not effect that depending on the implementation of each IDE. Having @Input on a property will result in the IDE showing you that property on an intellisense window when you write the HTML markup for that component.

Another risk factor is future support for minification/uglification in typescript. Private properties, as the name suggests, are used inside the class nowhere else. This trait means the complier can change the names of private properties so they take less bytes, it also makes them "more private" as the identifier might change from build to build. For example: private mySpecialProperty: string after minification will be p1 and the compiler will change all references to this identifier in the class to match p1. So, having this today will work but in the future it might limit build features.

Another point to consider is that while angular does not care about modifiers your compiler does, so dynamic component creation will be limited. In other word, creating components in html markup will work without any issues but dynamically creating components using the ComponentResolver -> ComponentFactor will be limited since you won't be able to assign those inputs to the instance of your components using code. If you're not planning to do so, you're good.

If you're building components to be used by others, public modifier is mandatory for @Input/@Output. The users of you'r component should be able to dynamically create your components.

This also answers the question about accessing these properties on a parent/child component getting reference to the coffee component. Binding will be possible via template markup only. For example, you won't be able to manually register to EventEmitters registered on the coffee component. This is sometimes required, see THIS scenario as one example.

As for lifecycle hooks, it should not have any effect since angular does not check the type but does an existance check.

So, to sum up, in most use cases you shouldn't have any issues but as you'r app progresses you might tackle some issues, or not. You might also have to opt-out of advanced minification features in the future...

这篇关于Angular2 @Inputs 应该是公开的,还是我们可以/应该通过将它们设为私有来拥有更严格的 API?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆