https://www.jb51.net/article/133868.htmphp
此次給你們帶來Angular2 父子組件通訊方式,使用Angular2 父子組件通訊方式的注意事項有哪些,下面就是實戰案例,一塊兒來看一下。html
Angular2官方文檔對組件交互這塊有詳細的介紹-->文檔--組件之間的交互。按文檔介紹,組件間交互的方式一共有4種,包括:git
-
經過輸入型綁定把數據從父組件傳到子組件(@Input decoration);子組件暴露一個EventEmitter屬性(@Output decoration),當事件發生時,利用該屬性emits向父組件發射事件。github
-
父組件與子組件經過本地變量互動。(# var)web
-
父組件調用@ViewChild。app
-
父組件和子組件經過服務來通信。函數
我在這裏只總結、詳細介紹3種我在項目中使用過的方法,看完本文大概能作到以下的效果:學習
建立項目,項目結構以下:this
經過@Input、@Output裝飾器進行父、子組件間的通訊spa
@Input:該屬性綁定用於父組件向子組件傳遞數據。子組件能夠經過如下兩種方法截取屬性的變動:
-
使用一個輸入屬性的setter,以攔截父組件中值得變化。
-
經過ngOnchanges()來截聽輸入屬性值的變化。
@Output:該數據綁定用於子組件向父組件傳遞數據和事件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<!--parent.component.html-->
<p style= "width: 1000px;margin: auto" >
<p class = "card" style= "width: 500px;float: left" >
<p class = "card-header" >
父組件
</p>
<p class = "card-body" >
<h5 class = "card-title" >父組件</h5>
<p class = "form-group" >
<label for = "input" >父組件輸入:</label>
<input type= "text"
class = "form-control"
id= "input"
placeholder= "Input something"
[(ngModel)]= "parentPrint"
>
<label for = "output" >父組件輸出:</label>
<input type= "text"
class = "form-control"
id= "output"
placeholder= "Output something"
[(ngModel)]= "contentFromChild"
>
</p>
</p>
</p>
<app-child
[fromParent]= "parentPrint"
(fromChild)= "fromChild($event)"
></app-child>
</p>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<!--child.component.html-->
<p class = "card" style= "width: 500px;" >
<p class = "card-header" >
子組件
</p>
<p class = "card-body" >
<h5 class = "card-title" >子組件</h5>
<p class = "form-group" >
<label for = "input" >子組件輸入:</label>
<input type= "text"
class = "form-control"
id= "input"
placeholder= "Input something"
[(ngModel)]= "contentFromChild"
>
<label for = "output" >子組件輸出:</label>
<input type= "text"
class = "form-control"
id= "output"
placeholder= "Output something"
[(ngModel)]= "fromParent"
>
</p>
<button class = "btn btn-primary" (click)= "clickChild()" >Output方式</button>
</p>
</p>
|
效果以下:(一、父組件輸入,子組件可同步輸出;二、子組件輸入須要(三、)點擊按鈕觸發發射事件,將數據傳送給父組件。)
@Input:父組件輸入的同時,子組件能同步獲取數據進行顯示。核心代碼以下:
1 2 3 4 5 6 7 8 |
parentPrint: any;
[(ngModel)]= "parentPrint"
<app-child [fromParent]= "parentPrint" ></app-child>
@Input() fromParent;
[(ngModel)]= "fromParent"
|
經過setter截聽輸入屬性值的變化,在子組件中聲明一個私有變量來獲取父組件傳遞過來的數據,從而屏蔽上層獲取下層信息。(簡單一點就是不讓父組件知道子組件用什麼東西去接收傳過來的數據)經過這種方法也能夠得到一樣的效果。
1 2 3 4 5 6 7 8 9 |
private _fromParent: any;
@Input()
set fromParent(fromParent: any) {
this._fromParent = fromParent;
}
get fromParent(): any {
return this._fromParent;
}
|
@Output:父組件接收子組件的數據時,子組件暴露一個EventEmitter屬性,當事件發生時,子組件利用該屬性emits(向上彈射)事件。父組件綁定到這個事件屬性,並在事件發生時做出迴應。核心代碼以下:
1 2 3 4 5 6 7 8 |
@Output() fromChild = new EventEmitter<any>();
<button class = "btn btn-primary" (click)= "clickChild()" >Output方式</button>
clickChild() {
console.log( 'click child' , this.contentFromChild);
this.fromChild.emit(this.contentFromChild);
}
|
1 2 3 4 5 6 7 8 9 10 11 12 |
[(ngModel)]= "contentFromChild"
<app-child
[fromParent]= "parentPrint"
(fromChild)= "fromChild($event)"
></app-child>
fromChild(event) {
console.log(event);
this.contentFromChild = event;
}
|
父組件經過調用@ViewChild()來獲取子組件的數據
若是父組件的類須要讀取子組件的屬性和值或調用子組件的方法時,就能夠把子組件做爲ViewChild,注入到父組件裏面。ViewChild顧名思義就是能夠看見子組件裏面的屬性和方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<!--parent.component.html-->
<p style= "width: 1000px;margin: auto" >
<p class = "card" style= "width: 500px;float: left" >
<p class = "card-header" >
父組件
</p>
<p class = "card-body" >
<h5 class = "card-title" >父組件</h5>
<p class = "form-group" >
<label for = "viewoutput" >ViewChild父組件輸出:</label>
<input type= "text"
class = "form-control"
id= "viewoutput"
placeholder= "ViewChild父組件輸出"
[(ngModel)]= "viewOutput"
>
</p>
<button class = "btn btn-primary" (click)= "clickView()" >ViewChild方式</button>
</p>
</p>
<app-child></app-child>
</p>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<!--child.component.html-->
<p class = "card" style= "width: 500px;" >
<p class = "card-header" >
子組件
</p>
<p class = "card-body" >
<h5 class = "card-title" >子組件</h5>
<p class = "form-group" >
<label for = "input" >子組件輸入:</label>
<input type= "text"
class = "form-control"
id= "input"
placeholder= "Input something"
[(ngModel)]= "contentFromChild"
>
</p>
</p>
</p>
|
效果以下:
父組件核心代碼:
1 2 3 4 5 6 7 8 |
@ViewChild(ChildComponent)
private childComponent: ChildComponent;
clickView() {
this.viewOutput = this.childComponent.contentFromChild;
}
|
1 2 3 |
[(ngModel)]= "viewOutput"
<button class = "btn btn-primary" (click)= "clickView()" >ViewChild方式</button>
|
父組件和子組件經過服務來通信
父組件和它的子組件共享同一個服務,利用該服務在家庭內部實現雙向通信。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<!--parent.component.html-->
<p style= "width: 1000px;margin: auto" >
<p class = "card" style= "width: 500px;float: left" >
<p class = "card-header" >
父組件
</p>
<p class = "card-body" >
<h5 class = "card-title" >父組件</h5>
<p class = "form-group" >
<label for = "serviceoutput" >父組件服務輸入:</label>
<input type= "text"
class = "form-control"
id= "serviceoutput"
placeholder= "服務輸入"
[(ngModel)]= "serviceInput"
>
</p>
<button class = "btn btn-primary" (click)= "clickService()" >Service方式</button>
</p>
</p>
<app-child></app-child>
</p>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<!--child.component.html-->
<p class = "card" style= "width: 500px;" >
<p class = "card-header" >
子組件
</p>
<p class = "card-body" >
<h5 class = "card-title" >子組件</h5>
<p class = "form-group" >
<label for = "serviceoutput" >子組件服務輸入:</label>
<input type= "text"
class = "form-control"
id= "serviceoutput"
placeholder= "服務輸入"
[(ngModel)]= "serviceInput"
>
</p>
<button class = "btn btn-primary" (click)= "clickService()" >Service方式</button>
</p>
</p>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import {Injectable} from '@angular/core' ;
import {Subject} from 'rxjs/Subject' ;
import {Observable} from 'rxjs/Observable' ;
@Injectable()
export class MeditorService {
private subject = new Subject<MeditorMsg>();
constructor() {}
public getObservable(): Observable<MeditorMsg> {
return this.subject.asObservable();
}
public push(msg: MeditorMsg) {
this.subject.next(msg);
}
}
export interface MeditorMsg {
id: string;
body: any;
}
|
效果以下:
父子組件的核心代碼相似,在構造函數中將該服務實例注入到自身,父子組件都有一個惟一的id。不管是父組件仍是子組件調用push()方法推送數據,雙方都能接收到數據,這時候就要根據id來判斷是要父組件使用數據仍是子組件使用數據。核心代碼以下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
subscription: Subscription = null;
constructor(
private meditor: MeditorService
) {
this.subscription = meditor.getObservable().subscribe(
msg => {
console.log(msg);
if (msg.id === 'parent' ) {
this.serviceInput = msg.body;
}
}
);
}
clickService() {
this.meditor.push({id: 'parent' , body: this.serviceInput});
}
constructor(
private meditor: MeditorService
) {
this.subscription = meditor.getObservable().subscribe(
msg => {
console.log(msg);
if (msg.id === 'child' ) {
this.serviceInput = msg.body;
}
}
);
}
clickService() {
this.meditor.push({id: 'parent' , body: this.serviceInput});
}
|
我上面寫的還不是很完善,就是在生命週期結束前,也就是在onDestroy週期中,要取消訂閱。
以上,就是最近在使用的組件交互的總結。我的以爲經過服務來交互的可擴展性更強。例如,咱們項目中用到了一個動態顯示的側欄,不一樣時期點擊顯示側欄要顯示不一樣的東西。這個時候把側欄做爲父組件,子組件做爲消息的一部分傳遞給父組件,父組件根據子組件名動態生成模板,顯示在側欄上面。說了這麼多廢話大概就是下圖的意思:
最後附上demo源碼:父子組件交互demo
以上就是本文的所有內容,但願對你們的學習有所幫助,也但願你們多多支持腳本之家。