angular 組件通信的幾種實(shí)現(xiàn)方式
單頁面應(yīng)用組件通信有以下幾種,這篇文章主要講 Angular 通信

- 父組件 => 子組件
- 子組件 => 父組件
- 組件A = > 組件B
| 父組件 => 子組件 | 子組件 => 父組件 | sibling => sibling |
|---|---|---|
| @input | @output | |
| setters (本質(zhì)上還是@input) | 注入父組件 | |
| ngOnChanges() (不推薦使用) | ||
| 局部變量 | ||
| @ViewChild() | ||
| service | service | service |
| Rxjs的Observalbe | Rxjs的Observalbe | Rxjs的Observalbe |
| localStorage,sessionStorage | localStorage,sessionStorage | localStorage,sessionStorage |
上面圖表總結(jié)了能用到通信方案,期中最后3種,是通用的,angular的組件之間都可以使用這3種,其中Rxjs是最最牛逼的用法,甩redux,promise,這些同樣基于函數(shù)式的狀態(tài)管理幾條街,下面一一說來
父組件 => 子組件
@input,最常用的一種方式
@Component({
selector: 'app-parent',
template: '<div>childText:<app-child [textContent] = "varString"></app-child></div>',
styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
varString: string;
constructor() { }
ngOnInit() {
this.varString = '從父組件傳過來的' ;
}
}
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'app-child',
template: '<h1>{{textContent}}</h1>',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
@Input() public textContent: string ;
constructor() { }
ngOnInit() {
}
}
setter
setter 是攔截@input 屬性,因?yàn)槲覀冊诮M件通信的時(shí)候,常常需要對輸入的屬性處理下,就需要setter了,setter和getter常配套使用,稍微修改下上面的child.component.ts
child.component.ts
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'app-child',
template: '<h1>{{textContent}}</h1>',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
_textContent:string;
@Input()
set textContent(text: string){
this._textContent = !text: "啥都沒有給我" ? text ;
} ;
get textContent(){
return this._textContent;
}
constructor() { }
ngOnInit() {
}
}
onChange
這個(gè)是通過angular生命周期鉤子來檢測,不推薦使用,要使用的話可以參angular文檔
@ViewChild()
@ViewChild() 一般用在調(diào)用子組件非私有的方法
import {Component, OnInit, ViewChild} from '@angular/core';
import {ViewChildChildComponent} from "../view-child-child/view-child-child.component";
@Component({
selector: 'app-parent',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
varString: string;
@ViewChild(ViewChildChildComponent)
viewChildChildComponent: ViewChildChildComponent;
constructor() { }
ngOnInit() {
this.varString = '從父組件傳過來的' ;
}
clickEvent(clickEvent: any) {
console.log(clickEvent);
this.viewChildChildComponent.myName(clickEvent.value);
}
}
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-view-child-child',
templateUrl: './view-child-child.component.html',
styleUrls: ['./view-child-child.component.css']
})
export class ViewChildChildComponent implements OnInit {
constructor() { }
name: string;
myName(name: string) {
console.log(name);
this.name = name ;
}
ngOnInit() {
}
}
局部變量
局部變量和viewChild類似,只能用在html模板里,修改parent.component.html,通過#viewChild這個(gè)變量來表示子組件,就能調(diào)用子組件的方法了.
<div class="panel-body">
<input class="form-control" type="text" #viewChildInputName >
<button class=" btn btn-primary" (click)="viewChild.myName(viewChildInputName.value)">局部變量傳值</button>
<app-view-child-child #viewChild></app-view-child-child>
</div>
child 組件如下
@Component({
selector: 'app-view-child-child',
templateUrl: './view-child-child.component.html',
styleUrls: ['./view-child-child.component.css']
})
export class ViewChildChildComponent implements OnInit {
constructor() { }
name: string;
myName(name: string) {
console.log(name);
this.name = name ;
}
ngOnInit() {
}
}
子組件 => 父組件
@output()
output這種常見的通信,本質(zhì)是給子組件傳入一個(gè)function,在子組件里執(zhí)行完某些方法后,再執(zhí)行傳入的這個(gè)回調(diào)function,將值傳給父組件
parent.component.ts
@Component({
selector: 'app-child-to-parent',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.css']
})
export class ChildToParentComponent implements OnInit {
childName: string;
childNameForInject: string;
constructor( ) { }
ngOnInit() {
}
showChildName(name: string) {
this.childName = name;
}
}
parent.component.html
<div class="panel-body">
<p>output方式 childText:{{childName}}</p>
<br>
<app-output-child (childNameEventEmitter)="showChildName($event)"></app-output-child>
</div>
child.component.ts
export class OutputChildComponent implements OnInit {
// 傳入的回調(diào)事件
@Output() public childNameEventEmitter: EventEmitter<any> = new EventEmitter();
constructor() { }
ngOnInit() {
}
showMyName(value) {
//這里就執(zhí)行,父組件傳入的函數(shù)
this.childNameEventEmitter.emit(value);
}
}
注入父組件
這個(gè)原理的原因是父,子組件本質(zhì)生命周期是一樣的
export class OutputChildComponent implements OnInit {
// 注入父組件
constructor(private childToParentComponent: ChildToParentComponent) { }
ngOnInit() {
}
showMyName(value) {
this.childToParentComponent.childNameForInject = value;
}
}
sibling組件 => sibling組件
service
Rxjs
通過service通信
angular中service是單例的,所以三種通信類型都可以通過service,很多前端對單例理解的不是很清楚,本質(zhì)就是
,你在某個(gè)module中注入service,所有這個(gè)modul的component都可以拿到這個(gè)service的屬性,方法,是共享的,所以常在app.moudule.ts注入日志service,http攔截service,在子module注入的service,只能這個(gè)子module能共享,在component注入的service,就只能子的component的能拿到service,下面以注入到app.module.ts,的service來演示
user.service.ts
@Injectable()
export class UserService {
age: number;
userName: string;
constructor() { }
}
app.module.ts
@NgModule({
declarations: [
AppComponent,
SiblingAComponent,
SiblingBComponent
],
imports: [
BrowserModule
],
providers: [UserService],
bootstrap: [AppComponent]
})
export class AppModule { }
SiblingBComponent.ts
@Component({
selector: 'app-sibling-b',
templateUrl: './sibling-b.component.html',
styleUrls: ['./sibling-b.component.css']
})
export class SiblingBComponent implements OnInit {
constructor(private userService: UserService) {
this.userService.userName = "王二";
}
ngOnInit() {
}
}
SiblingAComponent.ts
@Component({
selector: 'app-sibling-a',
templateUrl: './sibling-a.component.html',
styleUrls: ['./sibling-a.component.css']
})
export class SiblingAComponent implements OnInit {
userName: string;
constructor(private userService: UserService) {
}
ngOnInit() {
this.userName = this.userService.userName;
}
}
通過Rx.js通信
這個(gè)是最牛逼的,基于訂閱發(fā)布的這種流文件處理,一旦訂閱,發(fā)布的源頭發(fā)生改變,訂閱者就能拿到這個(gè)變化;這樣說不是很好理解,簡單解釋就是,b.js,c.js,d.js訂閱了a.js里某個(gè)值變化,b.js,c.js,d.js立馬獲取到這個(gè)變化的,但是a.js并沒有主動(dòng)調(diào)用b.js,c.js,d.js這些里面的方法,舉個(gè)簡單的例子,每個(gè)頁面在處理ajax請求的時(shí)候,都有一彈出的提示信息,一般我會(huì)在
組件的template中中放一個(gè)提示框的組件,這樣很繁瑣每個(gè)組件都要來一次,如果基于Rx.js,就可以在app.component.ts中放這個(gè)提示組件,然后app.component.ts訂閱公共的service,就比較省事了,代碼如下
首先搞一個(gè)alset.service.ts
import {Injectable} from "@angular/core";
import {Subject} from "rxjs/Subject";
@Injectable()
export class AlertService {
private messageSu = new Subject<string>(); //
messageObserve = this.messageSu.asObservable();
private setMessage(message: string) {
this.messageSu.next(message);
}
public success(message: string, callback?: Function) {
this.setMessage(message);
callback();
}
}
sibling-a.component.ts
@Component({
selector: 'app-sibling-a',
templateUrl: './sibling-a.component.html',
styleUrls: ['./sibling-a.component.css']
})
export class SiblingAComponent implements OnInit {
userName: string;
constructor(private userService: UserService, private alertService: AlertService) {
}
ngOnInit() {
this.userName = this.userService.userName;
// 改變alertService的信息源
this.alertService.success("初始化成功");
}
}
app.component.ts
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
message: string;
constructor(private alertService: AlertService) {
//訂閱alertServcie的message服務(wù)
this.alertService.messageObserve.subscribe((res: any) => {
this.message = res;
});
}
}
這樣訂閱者就能動(dòng)態(tài)的跟著發(fā)布源變化
總結(jié): 以上就是常用的的通信方式,各種場景可以采取不同的方法。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Angular實(shí)現(xiàn)跨域(搜索框的下拉列表)
angular.js 自帶jsonp,實(shí)現(xiàn)跨域,下面來實(shí)現(xiàn)搜索框的下拉列表功能,本文思路明確,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-02-02
angular4響應(yīng)式表單與校驗(yàn)實(shí)現(xiàn)demo
這篇文章主要介紹了angular4響應(yīng)式表單與校驗(yàn)實(shí)現(xiàn)demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
Angular 4 依賴注入學(xué)習(xí)教程之FactoryProvider的使用(四)
這篇文章主要給大家介紹了關(guān)于Angular 4 依賴注入之FactoryProvider使用的相關(guān)資料,文中介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Angular4具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。2017-06-06
總結(jié)AngularJS開發(fā)者最常犯的十個(gè)錯(cuò)誤
AngularJS是如今最受歡迎的JS框架之一,簡化開發(fā)過程是它的目標(biāo)之一,這使得它非常適合于元型較小的apps的開發(fā),但也擴(kuò)展到具有全部特征的客戶端應(yīng)用的開發(fā)。下面給大家總結(jié)了AngularJS開發(fā)者最常犯的十個(gè)錯(cuò)誤,有需要的可以參考學(xué)習(xí)下。2016-08-08
AngularJS實(shí)現(xiàn)與Java Web服務(wù)器交互操作示例【附demo源碼下載】
這篇文章主要介紹了AngularJS實(shí)現(xiàn)與Java Web服務(wù)器交互操作的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了AngularJS前臺ajax提交與javascript后臺處理的完整流程與實(shí)現(xiàn)技巧,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下2016-11-11
詳解Angular路由 ng-route和ui-router的區(qū)別
這篇文章主要介紹了詳解Angular路由 ng-route和ui-router的區(qū)別,分別介紹了兩種路由的用法和區(qū)別,有興趣的可以了解一下2017-05-05

