欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Angualr 組件間通信

 更新時(shí)間:2017年01月21日 08:25:07   作者:SerenoShen  
本篇文章主要介紹了Angualr 組件間通信,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

Angualr 組件間通信

約定: 遵循Angular官方的說法,下文中的AngularJS代指1.x版本,Angular代指Angular2及以后的升級版本。

采用Angular(或者任意MV*)的前端框架開發(fā)單頁應(yīng)用(SPA)時(shí),我們都可能會(huì)遇見如下的場景:

A組件和B組件之前需要相互通信,或是A路由狀態(tài)需要知道B路由狀態(tài)的信息等等業(yè)務(wù)需求。

這個(gè)時(shí)候就需要設(shè)計(jì)到采用一套合理的通信方案來解決數(shù)據(jù)同步,數(shù)據(jù)通信的問題。

AngularJS 組件間的數(shù)據(jù)通信

在AngularJS中,也就是Angular JS 1.x版本中,我們需要實(shí)現(xiàn)控制器間的通信,有很多種方案,常見的有:

1. 采用 SharedService, 利用共享的公共服務(wù)來實(shí)現(xiàn)數(shù)據(jù)交換。  

AngularJS中的Service被設(shè)計(jì)成單例的,這為這一方案,提供來底層的實(shí)現(xiàn)可行性,這一方案也是被廣泛采用的。

2. 利用AngularJS提供的事件機(jī)制,$rootScope.$broadcast/ $scope.$emit 配合 $on 方法實(shí)現(xiàn)。

該方案的實(shí)現(xiàn)具備一定的局限性,比如:$emit方法只能向上傳遞事件,而不能實(shí)現(xiàn)向下的事件傳播。但是進(jìn)行合理的搭配組合已經(jīng)基本夠用了。

3. 利用瀏覽器的SessionStorage或者LocalStorage進(jìn)行數(shù)據(jù)交換。

由于瀏覽器提供的這兩類本地存儲(chǔ)方案都提供了相應(yīng)的storage事件,所以我們也可以使用該方案進(jìn)行數(shù)據(jù)交換。使用該方案是應(yīng)該注意及時(shí)清理無關(guān)數(shù)據(jù)。

4. 采用響應(yīng)式的編程思想或者觀察者模式的應(yīng)用。關(guān)于這一類實(shí)現(xiàn),需要經(jīng)歷一個(gè)編程思想的轉(zhuǎn)變,之后會(huì)通過專門的文章進(jìn)行記錄。

5. 自身實(shí)現(xiàn)共享變量池。這個(gè)難度比較大,沒有一定的設(shè)計(jì)能力并不推薦。

由于AngularJS并不是本文的重點(diǎn),所以這里只簡單的提一下。后面介紹的Angular的方案也有許多可以通用的地方。

Angular 組件間的數(shù)據(jù)通信

SharedService

共享服務(wù)方案在新的Angular中依然可以使用,而且無需額外的學(xué)習(xí)成本。這里在之前的學(xué)習(xí)筆記里有記錄,不再紀(jì)錄了。

SharedService 搭配 RxJS

聽說 SharedService 和 RxJS 搭配更實(shí)用哦!這里的學(xué)習(xí)成本在于 RxJS ,RxJS只是 Rx思想的JS實(shí)現(xiàn)。這里強(qiáng)烈推薦學(xué)習(xí)Rx編程思想, 她的學(xué)習(xí)收益比絕對讓你想象不到。

RxJS不需要我們不斷的手動(dòng)去SharedService中檢查數(shù)據(jù)是否產(chǎn)生了變更,而是在數(shù)據(jù)有變化時(shí),主動(dòng)將變動(dòng)的數(shù)據(jù)推送給感興趣的任何訂閱者。

舉個(gè)栗子:

我們有一份隨時(shí)可能會(huì)發(fā)生變動(dòng)的數(shù)據(jù)存在了服務(wù)A中,在沒有使用RxJS(或是類似框架/庫)的情況下,我們想要知道數(shù)據(jù)的變化, 我們可能會(huì)采用輪詢的機(jī)制去不斷的詢問服務(wù)A,我們關(guān)心的數(shù)據(jù)是否發(fā)生了變化,如果變化了就做出相應(yīng)的動(dòng)作。我們處于一種盲目的主動(dòng)狀態(tài)。

更高級一點(diǎn)的實(shí)現(xiàn),就是我們可能把服務(wù)A實(shí)現(xiàn)稱為一個(gè)可被觀察的對象,這樣我們便能通過觀察服務(wù)A的狀態(tài)來獲取數(shù)據(jù)的變動(dòng)。

現(xiàn)在我們來使用RxJS實(shí)現(xiàn),RxJS現(xiàn)在可以理解為更高級的觀察者模式實(shí)現(xiàn)。當(dāng)使用來RxJS之后,在服務(wù)A中的數(shù)據(jù)發(fā)生變化時(shí),服務(wù)A會(huì)主動(dòng) 將變動(dòng)的數(shù)據(jù)推送給每一個(gè)感興趣的‘消費(fèi)者',這些消費(fèi)者處于被動(dòng)接受數(shù)據(jù),自主處理數(shù)據(jù)的狀態(tài)中。RxJS不同于普通觀察者模式的地方在于, 它提供來一系列的數(shù)據(jù)操作方法,比如:filter, map等等。這樣就便于我們更加精細(xì)的處理數(shù)據(jù)。

下面通過一段簡單的示例代碼來感受一下:

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class DataService {

 private data: any;
 private subject: Subject<any> = new Subject<any>();

 setData(data: any): void {
 this.data = data;
 this.subject.next(data);
 }

 getData(): Observable<any> {
 return this.subject.asObservable();
 }
}

上面的代碼中,我們簡單的實(shí)現(xiàn)了一個(gè)可觀察的數(shù)據(jù)服務(wù),下面我們來使用這個(gè)服務(wù)

import { Component, OnInit } from '@angular/core';

import { DataService } from './shared/Dataservice';

@Component({
 moduleId: module.id,
 selector: '<my-component></my-component>',
 templateUrl: '.name.component.html',
 providers: [DataService]
})
export class MyComponent implements OnInit {

 constructor(private dataService: DataService) {}

 ngOnInit() {
 // Will invoke data handler everytime
 // when other component use the setter this.dataService.setData()
 this.dataService.getData().subscribe(data => console.log(data));
 }
}

使用Angular底層提供的 @Input 和 @Output 裝飾器來實(shí)現(xiàn)組件間的通信服務(wù)

新的Angular采用Web Component的方式進(jìn)行組件的封裝,并將組件間的組織關(guān)系設(shè)計(jì)稱為樹狀結(jié)構(gòu)。這為應(yīng)用數(shù)據(jù)的流向,管理提供了良好的支持, 也使得我們可以在Angular應(yīng)用中使用一些別的庫,比如: Redux 思想?;谶@些設(shè)計(jì)理念,Angular為指令提供了更為強(qiáng)大的功能,組件也是指令。

采用 @Input 修飾屬性,實(shí)現(xiàn) parent -> child 組件間的通信

下面的示例代碼將展示如何設(shè)置一個(gè)組件的Input屬性

import { Component, Input, OnInit } from '@angular/core';

@Component({
 moduleId: module.id,
 selector: 'child-component',
 template: `I'm {{ name }}`
})
export class ChildComponent implements OnInit {

 @Input() name: string;

 constructor() { }

 ngOnInit() { }
}

上面的代碼中,我們實(shí)現(xiàn)了一個(gè)名叫ChildComponent的組件,這個(gè)組件的有一個(gè)采用@Input裝飾器修飾的屬性:name。

下面我們將展示如何使用這個(gè)這個(gè)組件,并為這個(gè)Input屬性賦值。

import { Component, OnInit } from '@angular/core';
import { ChildComponent } from './child-component';

@Component({
 moduleId: module.id,
 selector: 'parent-component',
 template: `<child-component [name]="childName"></child-component>`,
 // This is unnecessary when installing ChildComponent within Root NgModule
 directives: [ChildComponent]
})
export class ParentComponent implements OnInit {

 private childName: string;

 constructor() { }

 ngOnInit() { 
 this.childName = 'StevenShen';
 }
}

上面的代碼實(shí)現(xiàn)中,在父組件中,我們?yōu)樽咏M件的Input屬性設(shè)置了父組件中的特定值。關(guān)鍵點(diǎn)在如下片段:

<child-component [name]="childName"></child-component>

Angular在進(jìn)行AOT操作時(shí),會(huì)將特定的值注入給ChildComponent中。

如果你在CodePen,或是自己的本地實(shí)驗(yàn)上面的代碼你會(huì)發(fā)現(xiàn),和AngularJS的指令中采用'@', ‘=', ‘&'等修飾的屬性不一樣的地方。

當(dāng)父組件中的childName發(fā)生變化時(shí),ChildComponent中的name屬性并沒有感知到變化。這是怎么了,是不是感覺新版的Angular在 和我們開玩笑,wtf?。?!內(nèi)心的表情是這樣的 ○| ̄|_ 。(感覺一篇學(xué)習(xí)筆記開始被寫的畫風(fēng)突變了。。。)

將父組件的屬性變化映射到子組件中

上一小節(jié)的實(shí)現(xiàn),雖然在初始化子組件時(shí),我們可以將父組件的值反饋到子組件中。但是,初始化完成后,父組件中相關(guān)屬性的變化卻不能被子組件感知。

這無疑是讓我們內(nèi)心崩潰的。為什么和AngularJS不一樣了???別急,下面我們將來提供解決方案。

利用Angular提供的組件生命周期鉤子函數(shù)ngOnChanges來監(jiān)聽輸入屬性值的變化

需要實(shí)現(xiàn)讓子組件感知到父組件中相關(guān)屬性的變化,我們需要對Angualr組件的生命周期有一定的了解,采用Angular提供的組件生命周期的鉤子函數(shù), 進(jìn)行組件間數(shù)據(jù)的同步。(關(guān)于Angualr組件的生命周期,之后會(huì)有相關(guān)的學(xué)習(xí)筆記整理。到時(shí)候在加上鏈接。)這里直接上代碼:

import { Component, Input, SimpleChanges } from '@angular/core';

@Component({
 moduleId: module.id,
 selector: 'child-component',
 template: `I'm {{ name }}`
})
export class ChildComponent {

 @Input() name: string;

 ngOnChanges(changes: SimpleChanges) {
 this.name = changes['childName'].currentValue;
 }
}

采用ES5中的getter和setter方法進(jìn)行輸入屬性的監(jiān)聽

在ES5中,我們在定義一個(gè)對象的屬性時(shí),可以通過Object.defineProperty方法為一個(gè)對象的屬性設(shè)置關(guān)聯(lián)的getter和setter方法, 當(dāng)我們進(jìn)行這一操作后,以后該對象上的相關(guān)屬性的讀取和賦值操作,都會(huì)調(diào)用相應(yīng)的getter/setter方法進(jìn)行預(yù)處理或改變操作結(jié)果。

同樣的道理,在Angular中,我們通過設(shè)置和使用一個(gè)輸入屬性的setter方法,便可以攔截到父組件中相關(guān)值的變化,并進(jìn)行特定的數(shù)據(jù)處理。

這種方法比較直觀,直接上代碼:

父組件的代碼實(shí)現(xiàn):

import { Component } from '@angular/core';
@Component({
 moduleId: module.id,
 selector: 'name-parent',
 template: `
 <h2>Master controls {{names.length}} names</h2>
 <name-child *ngFor="let name of names" [name]="name"></name-child>
 `
})
export class ParentComponent {
 names = ['StevenShen', ' ', ' lei '];
}

子組件的代碼實(shí)現(xiàn)

import { Component, Input } from '@angular/core';
@Component({
 moduleId: module.id,
 selector: 'name-child',
 template: `<h3>"{{name}}"</h3>`
})
export class ChildComponent {
 name: string = 'default name';

 @Input()
 set name(name: string) {
 this.name = (name && name.trim()) || 'default name';
 }

 get name() { return this.name; }
}

采用 @Output 修飾屬性,實(shí)現(xiàn) child -> parent 組件間的通信

新版的 Angular 中,子組件和父組件間的通信,采用來事件的機(jī)制。這樣的設(shè)計(jì)有助于組件的復(fù)用和代碼的解耦;
我們不需要過多的關(guān)心組件的具體實(shí)現(xiàn),我們只需要知道一個(gè)組件它接收哪些數(shù)據(jù),并產(chǎn)生哪些輸出事件即可。

直接上代碼直觀了解一下:

@Component({
 moduleId: module.id,
 selector: 'child-component',
 template: `I'm {{ name }}`
})
export class ChildComponent {

 @Input() name: string;

 @Output() say: EventEmitter<boolean> = new EventEmitter<boolean>();

 ngOnChanges(changes: SimpleChange) {
 this.name = changes['childName'].currentValue;
 }

 speak() {
 this.say.emit(true);
 }
}

子組件變更完成后,我們來變更父組件的代碼實(shí)現(xiàn)。

import { Component, OnInit } from '@angular/core';
import { ChildComponent } from './child-component';

@Component({
 moduleId: module.id,
 selector: 'parent-component',
 template: `<child-component [name]="childName" (say)="isChildSpeak($event)"></child-component>`,
 // This is unnecessary when installing ChildComponent within Root NgModule
 directives: [ChildComponent]
})
export class ParentComponent implements OnInit {

 private childName: string;

 constructor() { }

 ngOnInit() { 
 this.childName = 'StevenShen';
 }

 isChildSpeak(isIt: boolean) {
 console.log('The child speak status is %s', isIt ? 'ture' : 'false');
 }
}

這樣一來就實(shí)現(xiàn)了父子組件間的通信了。

但是這樣的實(shí)現(xiàn)存在一定的局限性:父組件不能使用數(shù)據(jù)綁定來讀取子組件的屬性或調(diào)用子組件的方法.

通過 @ViewChild 獲取組件的控制器/模版進(jìn)行組件間的通信

除開使用 @Input 和 @Output 修飾器搭配Angular的生命周期鉤子函數(shù)進(jìn)行組件間通信。 我們還可以采用@ViewChild來進(jìn)行不同組件間的通信,而不僅僅局限于父子組件間的通信。同時(shí),采用@ViewChild的方式, 我們可以獲得更為精細(xì)的組件控制權(quán)限,比如在父組件中讀取子組件的屬性值或調(diào)用子組件的方法。我們依然采用上面的代碼來進(jìn)行改造。

對于ChildComponent組件的變更:

import { Component } from '@angular/core';

@Component({
 moduleId: module.id,
 selector: 'child-component',
 template: `I'm {{ name }}`
})
export class ChildComponent {
 public name: string;

 speak() {
 console.log('say something whitout EventEmitter');
 }
}

對于ParentComponent組件的變更:

import { Component, OnInit, AfterViewInit, ViewChild, ElementRef } from '@angular/core';
import { ChildComponent } from './child-component.ts';

@Component({
 moduleId: module.id,
 selector: 'parent-component',
 // attention #childCmp tag
 template: `
 <child-component #childCmp></child-component>
 <button (click)="child.name = childName"></button>
 `,
 // This is unnecessary when installing ChildComponent within Root NgModule
 directives: [ ChildComponent ]
})

export class ParentComponent implements OnInit, AfterViewInit {

 @ViewChild('childCmp') childCmp: ElementRef;


 constructor() { }

 ngOnInit() { 
 this.childCmp.name = 'StevenShen';
 }

 ngAfterViewInit() {
 this.childCmp.speak();
 }
}

通過上面的代碼改造,我們同樣可以實(shí)現(xiàn)不同組件間的通信,而且這樣的組件通信已經(jīng)不僅僅局限于父子組件間的通信了。

總結(jié)

由于技術(shù)水平和時(shí)間原因,這篇文章完成得比較粗略。主要整理的都是自己在工作中實(shí)際使用到的一些方案。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • AngularJS的內(nèi)置過濾器詳解

    AngularJS的內(nèi)置過濾器詳解

    在我們開發(fā)中經(jīng)常需要在頁面顯示給用戶的信息需要一定處理格式化,才能顯示給用戶。在angularjs中為我們提供了叫filter的指令,讓我們能夠很輕易就能做到著一些列的功能,angularjs內(nèi)部為我們提供了number等很多內(nèi)置的filter。
    2015-05-05
  • Angular 多級路由實(shí)現(xiàn)登錄頁面跳轉(zhuǎn)(小白教程)

    Angular 多級路由實(shí)現(xiàn)登錄頁面跳轉(zhuǎn)(小白教程)

    這篇文章主要介紹了Angular 多級路由實(shí)現(xiàn)登錄頁面跳轉(zhuǎn)(小白教程),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • angularjs http與后臺(tái)交互的實(shí)現(xiàn)示例

    angularjs http與后臺(tái)交互的實(shí)現(xiàn)示例

    這篇文章主要介紹了angularjs http與后臺(tái)交互的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • AngularJS 簡單應(yīng)用實(shí)例

    AngularJS 簡單應(yīng)用實(shí)例

    本文主要介紹AngularJS 的簡單應(yīng)用實(shí)例,這里對AngularJS的知識(shí)總結(jié),并提供實(shí)例代碼和應(yīng)用程序講解,有需要的小伙伴可以參考下
    2016-07-07
  • AngularJS基礎(chǔ) ng-cut 指令介紹及簡單示例

    AngularJS基礎(chǔ) ng-cut 指令介紹及簡單示例

    本文主要介紹AngularJS ng-cut 指令,這里對ng-cut指令的基礎(chǔ)資料進(jìn)行了整理,和詳細(xì)介紹,并附上代碼示例和實(shí)現(xiàn)效果圖,學(xué)習(xí)AngularJS 指令的朋友可以參考下
    2016-08-08
  • AngularJS基礎(chǔ) ng-submit 指令簡單示例

    AngularJS基礎(chǔ) ng-submit 指令簡單示例

    本文主要介紹AngularJS ng-submit 指令,這里對ng-submit 指令的基礎(chǔ)資料做了詳細(xì)介紹整理,并附有代碼示例,有需要的小伙伴可以參考下
    2016-08-08
  • Angular8升級至Angular13遇到的問題解決

    Angular8升級至Angular13遇到的問題解決

    這幾天升級公司的一個(gè)Angular項(xiàng)目遇到了一些問題,下面這篇文章主要給大家介紹了關(guān)于Angular8升級至Angular13遇到的問題解決,文中介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • angularJS 中input示例分享

    angularJS 中input示例分享

    這篇文章主要介紹了angularJS 中input示例分享,需要的朋友可以參考下
    2015-02-02
  • Angular指令之restict匹配模式的詳解

    Angular指令之restict匹配模式的詳解

    這篇文章主要介紹了Angular指令之restict匹配模式的詳解的相關(guān)資料,這里對Angularjs 中restict匹配模式進(jìn)行詳解并列舉了四種模式進(jìn)行比較,需要的朋友可以參考下
    2017-07-07
  • AngularJS ng-mousedown 指令

    AngularJS ng-mousedown 指令

    本文主要介紹AngularJS ng-mousedown 指令,這里幫大家整理了ng-mousedown 指令的基本資料,并附代碼示例,有需要的朋友可以參考下
    2016-08-08

最新評論