Angular 2 - 组件之间的双向通信

Angular 2 - Two way communication between components

我有这段代码...这是我正在尝试构建的示例教程应用程序,它反映了开发人员的日常基本需求。 实际上,当用户在 parent 组件上键入 "fire" 时,child 会执行一个事件,该事件会向 parent 发送单词 "booom" - 这是一个示例演示使用 @Input 和 OnChanges 向 parent 组件发送消息的 child 组件之间的通信。

现在,我正在尝试做不同的事情:当用户按下回车键 (keyCode == 13)。有了这个,我们将有一个组件之间双向通信的场景。

最好的方法是什么?

child.component

import {Component, Input, OnChanges, EventEmitter,Output, Injectable} from 'angular2/core';
@Injectable()
@Component({
selector: 'child-component',
template: `<p>I'm the child component</p>
`
})
export class ChildComponent implements OnChanges { 
@Input() txt: string;
@Output() aim: EventEmitter<any> = new EventEmitter();
ngOnChanges(changes: {[propName: string]: SimpleChange}) {
    var t = changes['txt'].currentValue;
    if(t == 'fire') {
        console.log('Fire !!!');
        this.aim.emit("booom !!!");
    }
}
}

parent.component

import {Component} from 'angular2/core';
import {ChildComponent} from './child.component'
@Component({
selector: 'parent-component',
directives : [ChildComponent]
template: `<p>I'm the parent component</p>
<input type="textbox" [(ngModel)]="theModel" (keydown)="arrow($event)">
<p>feedback: {{feedback}}</p>
<child-component txt="{{theModel}}" (aim)="feedback=$event"></child-component>
`
})
export class ParentComponent { 
theModel;
feedback;
arrow (evt){
    if(evt.keyCode ==13) {
        //Need to cause an event on the child - a message like "Target Locked"
    };
}
}

您可以提供 EventEmitter 作为 child 组件的输入:

@Component({
  selector: 'child-component'
  (...)
})
export class ChildComponent {
  @Input()
  parentEventEmitter:EventEmitter;

  ngOnInit() {
    this.parentEventEmitter.subscribe((event) => {

    });
  }
}

然后 child 可以订阅它以得到通知...

EventEmitter 将在 parent 组件中以这种方式提供:

<child-component
   [parentEventEmitter]="theEventEmitterFromTheParent">
</child-component>

您需要在父组件中实现并订阅事件发射器。您的发射器名称必须与绑定值名称匹配 +'Change' 示例:如果您的值名称是 "sum" 您的事件需要是 "sumChange" 这样您就可以从父类进行 2 种方式绑定[(sum)] = "value"。这是一个简单的例子:

https://plnkr.co/edit/efOGIJ0POh1XQeRZctSx?p=preview

My doubt is about to do the opposite way: Child capture the event of the parent. Remember the child will never have the selector of the parent. That's why it's really different.

我认为混淆是因为您不需要活动。对于parent → child 通信,只需在child 中添加另一个输入属性。并绑定一个 parent 属性 到它:

<child-component [anotherInputProperty]="someParentProperty" ...

然后,每当您在 parent 组件中更改 someParentProperty 的值时,Angular 更改检测会将新值传播到 child:

if(evt.keyCode === 13) {
    // Need to cause an event on the child - a message like "Target Locked".
    // Just change the property value:
    this.someParentProperty = "some new value";
    // Angular will take care of propagating the new value to the child
};

如果你想让child在输入属性值改变时执行一些逻辑,在child.

中实现ngOnChanges()

如果问题是您不想每次都更改消息,那么您可以

  • 使用 并让 child subscribe() 到 Observable,或者
  • 使用随机值作为前缀或后缀,并使用 | 或其他可以拆分的字符将其与消息分开,以便在 child 中轻松提取消息。

您还可以在共享服务中使用 Subject 而不是 Observable:参见 Parent and children communicate via a service