简体   繁体   English

Angular 2 属性绑定:EventEmitters 如何工作?

[英]Angular 2 property binding: how do EventEmitters work?

I've been working on learning Angular 2 two-way binding, and I've put together a demo that binds a component's property to another, contained component's property, as well as to several text fields.我一直在学习 Angular 2 双向绑定,并且我已经制作了一个演示,将一个组件的属性绑定到另一个包含的组件的属性,以及几个文本字段。 Unfortunately, a lot of it seems like magic to me, which makes it awfully hard to debug when the magic isn't working.不幸的是,很多对我来说似乎是魔术,这使得在魔术不起作用时调试非常困难。 In particular, the demo reveals several places where I don't yet fully understand binding;特别是,该演示揭示了我还没有完全理解绑定的几个地方; this question is the first of what may be several on this topic.这个问题是关于这个主题的几个问题中的第一个。

(The demo is at http://plnkr.co/edit/IUTy5p?p=preview , in case you want to follow along at home...) (演示位于http://plnkr.co/edit/IUTy5p?p=preview ,以防您想在家中学习...)

The code implements a parent component with a pName string property, and a contained, child component with a cName property.该代码实现了一个带有pName字符串属性的父组件和一个带有cName属性的包含的子组件。 The parent's property is two-way bound to the child's property using the banana box syntax:父属性使用香蕉盒语法双向绑定到子属性:

<child [(cName)]="pName"></child>

Inside the child is a display of the cName property, as well as three text inputs, each of which is in some way bound to the cName property.cName内部是cName属性的显示,以及三个文本输入,每个文本输入都以某种方式绑定到cName属性。 The second text input is the important one here:第二个文本输入在这里很重要:

<input type="text" [ngModel]="cName" (ngModelChange)="cNameChange.emit($event)">

The ngModelChange event invokes an emit() method on an EventEmitter whose name cNameChange is derived from the cName property's name:所述ngModelChange事件调用一个emit()上的方法EventEmitter其名称cNameChange从衍生cName属性的名称:

@Output() public cNameChange:EventEmitter<String> = new EventEmitter<String>();

So, if you edit the second text input's value, the child's cName property changes, the other two text inputs change their values, and the parent's pName property changes.因此,如果您编辑第二个文本输入的值,子项的cName属性会更改,其他两个文本输入的值会更改,而父项的pName属性会更改。

But, how ?但是,怎么样

This can be split into two related questions:这可以分为两个相关的问题:

  1. How does emitting that event change the cName property?发出该事件如何更改cName属性?
  2. How does changing the child's cName property end up changing the parent's pName property?更改子项的cName属性如何最终更改父项的pName属性?

The only real magic is the [()] syntax, which is specified by Angular.唯一真正的魔法是[()]语法,它是由 Angular 指定的。 The rest can explained in the following sections其余的可以在以下部分中解释

When we use [(cData)]="pData" it is the same as using当我们使用[(cData)]="pData"它与使用相同

[cData]="pData" (cDataChange)="pData = $event"

where when an event is emitted to cDataChange , Angular guarantees to set the value of the bound input property ( [cData]="pData" ), in this case pData to the value emitted from the cDataChange当一个事件被发送到cDataChange ,Angular 保证设置绑定输入属性的值( [cData]="pData" ),在这种情况下pData为从cDataChange发出的值

  1. How does emitting that event change the cName property?发出该事件如何更改cName属性?
@Component({
  template: `
    <input type="text" [ngModel]="cName" (ngModelChange)="cNameChange.emit($event)">
  `
})
export class ChildComponent {
  @Input() public cName:string = 'thisIsIgnored';
  @Output() public cNameChange:EventEmitter<String> = new EventEmitter<String>();
}

@Component({
  selector: 'parent',
  template: `
    <child [(cName)]="pName"></child>
  `
})
export class App {
  pName:string;

  constructor() {
    this.pName = 'InitialName'
  }
}

The parent pData is two way bound to child cData using the simplified syntax [(cData)]="pData" .pData使用简化语法[(cData)]="pData"以两种方式绑定到子cData This means that the parent is both providing the @Input('cData') to the child and listenting to the cNameChange event, which automatically changes the bound property, in this case pData .这意味着父级同时向子级提供@Input('cData')cNameChange事件,该事件会自动更改绑定属性,在本例中为pData This is the only really magical part.这是唯一真正神奇的部分。 But it is what is described in Angular docs, so we just accept it to be true.但它是 Angular 文档中所描述的,所以我们只是接受它是真的。

So when you type into the second child input, it emits the cDataChange event and the pData gets changed, per Angular specifications.因此,当您输入第二个子输入时,它会根据 Angular 规范发出cDataChange事件并且pData发生更改。 That pData is also the input for cData , so that cData also needs to change to match the pData input. pData也是cData的输入,因此cData也需要更改以匹配pData输入。

You can confirm that parent is responsible for the cData change by commenting out the first and third input of the child, and just adding您可以确认母公司负责cData注释出孩子的第一和第三输入,只是加入的变化

<li>cName: {{ cName }}</li>
  1. How does changing the child's cName property end up changing the parent's pName property?更改子项的cName属性如何最终更改父项的pName属性?

You're not ever really changing it (explicitly) at any point.在任何时候你都不会真正改变它(明确地)。 This is all handled by the two-way binding.这一切都由双向绑定处理。 If you add something that does explicitly change it, say如果添加的东西,明确地改变,比方说

<button (click)="cName = 'hello'">Change</button>

or just simply typing in the third input.或者只是简单地输入第三个输入。 When you click the button or type, you will see that it does not change the parent, but the children see the change because they're getting input from the cData .当您单击按钮或类型时,您将看到它不会更改父项,但子项会看到更改,因为他们从cData获取输入。 The only way the parent will see the change is cData is only if the cDataChange event is emitted with the new value.只有当cDataChange事件与新值一起发出时,父级才能看到更改的唯一方式是cData

So what actually changes the parent is the activity discussed in the previous point.所以实际上改变父级的是上一点中讨论的活动。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM