[英]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:这可以分为两个相关的问题:
cName
property?cName
属性?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
发出的值
- 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>
- How does changing the child's
cName
property end up changing the parent'spName
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.