2016-03-15 125 views
1

我已經這段代碼...這是一個示例教程應用程序,我試圖構建它反映了開發人員的日常需求。 實際上,當用戶在父組件上鍵入「fire」時,子節點執行向父節點發送單詞「booom」的事件 - 這是一個示例,演示使用@Input向子組件發送消息的子組件間的通信和OnChanges。Angular 2 - 組件之間的雙向溝通​​

現在,我試着做不同的事情:當用戶按下回車鍵(keyCode == 13)時,父母應該用一些方法告訴孩子一條類似「Target Locked」的消息給孩子。有了這個,我們將有一個組件間雙向通信的場景。

什麼是最好的方法?

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" 
    }; 
} 
} 
+0

使用'@Input()'從父項與子項進行通信,'@Output()'從子項與父項進行通信或使用服務。 –

+0

「現在,我試着做不同的事情:」 - 我看不出這裏有什麼不同。只需使用相同的輸入和輸出屬性併發送不同的消息,或添加另一組輸入和輸出屬性。還要檢出[Component Interaction cookbook](https://angular.io/docs/ts/latest/cookbook/component-communication.html) –

+0

父級使用導入和選擇器合併子級ny。所以,父母可以從孩子那裏捕捉(目標)事件。我的懷疑即將採取相反的方式:孩子捕捉父母的事件。記住孩子永遠不會有父母的選擇。這就是爲什麼它真的不同。明白了嗎? –

回答

2

我的疑問是關於做相反的方式:兒童捕捉父的事件。記住孩子永遠不會有父母的選擇。這就是爲什麼它真的不同。

我覺得困惑是圍繞着你不需要事件的事實。對於父母→子女溝通,只需向孩子添加另一個輸入屬性即可。和parent屬性綁定到它:

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

然後,當你在父組件改變someParentProperty值,角度變化檢測將新值傳播到孩子:

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 
}; 

如果您當輸入的屬性值發生變化時,要讓孩子執行一些邏輯,在孩子中執行ngOnChanges()

如果問題是,你不希望每次更改消息,那麼你既可以

  • 使用a shared service with an Observable並有孩子subscribe()到觀察的,或
  • 前綴或後綴的帶有隨機值的消息,並使用|或其他可以拆分的字符將其與消息分開,以便在子項中可以輕鬆提取消息。

您也可以在共享服務中使用Subject而不是Observable:請參閱Parent and children communicate via a service

+0

ty,Mark!我會檢查你的答案,直到明天,如果適用,我不會忘記標記爲答案。 ty! –

+0

您的解決方案正是我在做的。老實說,它沒有多少優雅,但看起來像它是唯一可以接受的(例如,在我的真實項目中,我的父母中有一個輸入框。我需要在每次用戶按下我的子事件時引起反應(事件)如果(event.keyCode == 40){this.myChildProperty ='down,'+ Math.random();} - 如果我按下兩次,隨機會確保事件將被執行,但老實說,我真的不喜歡這個解決方案,但是因爲它是唯一可以接受的,所以確保 –

+0

@ MarcoS.Junior,因爲你不斷提到這個詞「事件」,聽起來像共享服務方法(使用Observable或Subject)將更適合您的用例,而不是輸入屬性。 –

2

你可以提供一個EventEmitter的子組件的輸入:

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

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

    }); 
    } 
} 

這孩子然後訂閱就可以了被通知...

EventEmitter將提供這樣的父組件內:

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

無法實現:ngOnInit(){this.parentEventEmitter.subscribe((event)=> { }); ---> this.parentEventEmitter.subscribe不是[ParentComponent中的箭頭中的函數 - 我將它放在https://plnkr.co/edit/nqlCl6r5Ib64MCYJA5v9 –

1

您需要實現事件發射器和訂閱它的父組件。您的發射器名稱必須匹配綁定的數值名稱+'更改'例如:如果您的數值名稱爲「總和」,則您的事件需要爲「sumChange」,您可以使用這種方法從父數據庫中進行雙向綁定[(sum)] = "value"。這裏是一個普拉克例如:

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

+0

上的plunker中。聲音真的很有趣,Mohy!我會在星期一學習,但我喜歡! –

+0

基本上,您爲父項設置了一個值。面臨的挑戰是讓父母在孩子身上發生事件。在我的例子中,我將一個事件從孩子提升到父母。 –

+0

好吧,如果你注意到我改變了父母的價值,它反映在孩子身上,當我從孩子改變它時,它反映到父母身上。這是非常雙向的溝通。你想要完成不同的事情嗎? –