AngularJS 2 組件交流方式

如下的測試例子均可以在 github 找到,可是最近好像不太穩定。javascript

其實 ng2 在這方面作得挺好的,用起來也很簡單,因此看完基本就能夠動手寫一寫。強大並不止是這一方面,在寫這些的過程當中,經過一些配置,讓開發很純粹,有時間再錄一個新手入門的開發教程。css

(1) 父組件向子組件流入數據

這種方式是最簡單的,在 ng2 中處理得很是完美,經過在子組件中標記 @Input() 輸入接口的方式進行接收父組件的值,我下面的 demo 主要分了幾種場景,儘量的多覆蓋不一樣狀況吧。html

基本上例子中覆蓋了常見的狀況:java

  • 直接傳入一個字符串的狀況,不須要綁定父組件的一個變量git

  • 綁定父組件變量的狀況,而後能夠在父組件中不斷修改github

  • 輸入別名的狀況,能夠在子組件中對輸入的變量名進行從新設置typescript

  • ngOnChanges() 在子組件中監聽屬性的修改app

  • 特殊狀況下,咱們須要對父組件傳入的數據進行過濾dom

  • @ViewChild() 註解的跨多層子組件的觀察方式函數

說了這麼多,來看一下實際的代碼吧。

// Parent component
import { Component, OnInit } from '@angular/core';
    
@Component({
    selector: 'app-parent',
    templateUrl: './parent.component.html',
    styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
    
    baby: string = '你的名字';
    
    constructor() { }
    
    ngOnInit() {
    }
    
}
// Parent html
<h3>請輸入 Baby 的名字:</h3>
<input [(ngModel)]="baby" type="text"> 
<app-child babyName="hello" [inputBabyName]="baby" aliasBabyName="我是別名"></app-child>
// Child component
import { Component, OnInit, Input, SimpleChange } from '@angular/core';

@Component({
    selector: 'app-child',
    templateUrl: './child.component.html',
    styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
    
    @Input() babyName: string;
    @Input() inputBabyName: string;
    @Input('aliasBabyName') aliasName: string;
    
    changes: string;
    
    constructor() { }
    
    ngOnInit() {
    }
    
    ngOnChanges(changes: SimpleChange) {
        this.changes = JSON.stringify(changes);
    }
}
// Child html
<h3>我是子組件的屬性(babyName) => {{babyName}}</h3>
<h3 style="color:red;">我是跟父組件來:{{inputBabyName}}</h3>
<h3>我是 aliasBabyName => aliasName:{{aliasName}}</h3>

那麼我須要過濾一下值要怎麼弄呢?

這樣咱們就能夠用到 setter 和 getter 的特性來作,具體以下:

// Child component
_filterName: string = '';
    
@Input()
set filterName(n: string) {
    this._filterName = n + 'wowo~~~';
}
    
get filterName() {
    return this._filterName;
}
// Parent html
<app-child [filterName]="babyName"></app-child>

這個其實也是用 @Input() 這個註解來作的,有點相似 computed 的概念吧,可是這樣作對於習慣 Java 的小夥伴是很友好的,其實經過一些權限的設置,還可以更加的強大。

@ViewChild() 的方式

這種方式我以爲更多的是,個人溝通邏輯存在於 TS 中的時候就很實用。而且是描述性的定義方式,因此邏輯也是清晰的。

// Parent component
// 方式1,定義了 `#` 的鉤子也是能夠引用的
@ViewChild('child') cc: ChildComponent;
    
// 直接觀察某一個子組件
@ViewChild(ChildComponent)
cc_other: ChildComponent;
    
// 調用的時候
this.cc.name = '變身啦!超級賽亞人';
this.cc_other.name = '變身啦!超級賽亞人 4';

能夠思考一下,是否任何形式的父組件流入子組件的方式,均可以觸發 ngOnChanges() 方法。

(2) 子組件向父組件通訊

從軟件的結構上來說,是上層抽象對底層的具體實現是隱藏的,因此具體層的東西最好儘量少的知道抽象層的事情,也許表達方式不同,可是這樣的話封閉性會好不少,更多的暴露是以某一個權限開放的接口形式。可是通訊是很複雜的東西,就好像人與人之間的聯繫是同樣的。好吧,咱們來具體說一會兒組件怎麼訪問父組件。主要經過的方式是:

  • 在子組件定義一個 @Output()EventEmitter<T> 對象,這個對象能夠是 Subject 的形式存在,也就是可使用 RxJS 的思想來作,其中 T 範型表示定義須要傳入的數據具體類型。

  • 父組件中定義一個本身的函數來修改自身的信息,或者再傳入其餘子組件使用。

// Parent component
import { Component, OnInit } from '@angular/core';
    
@Component({
    selector: 'app-parent',
    templateUrl: './parent.component.html',
    styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
    
    babyName: string;
    
    constructor() { }
    
    ngOnInit() {
    this.babyName = '小擼一號';
    }
    
    changeBabyName(newBabyName) {
        this.babyName = newBabyName;
    }
 
}
// Parent html
<h3>BabyName:{{babyName}}</h3>
<app-child (changeBabyName)="changeBabyName($event)"></app-child>
import { Component, OnInit, Output, EventEmitter } from '@angular/core';
    
@Component({
    selector: 'app-child',
    templateUrl: './child.component.html',
    styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
    
    @Output()
    changeBabyName: EventEmitter<string> = new EventEmitter<string>();
    
    rhashcode = /\d\.\d{4}/;
    
    constructor() { }
    
    ngOnInit() {
    }
    
    getNewBabyName(e) {
        let newName = this.makeHashCode('小擼新號');
        this.changeBabyName.next(newName);
    }
    
    /* UUID http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript */
    makeHashCode(prefix) {
        prefix = prefix || '60sky';
        return String(Math.random() + Math.random()).replace(this.rhashcode, prefix);
    }
}
<button (click)="getNewBabyName($event)">我要改我本身的名字</button>

其中須要注意的是父組件中方法注入的 $event 對象,這個對象在這裏注入的是子組件傳入的值,因此在父組件中就能夠直接使用了,我這裏定義了 string 類型的數據,因此傳入後定義接口的參數類型也是相對應的。

(3) 無關組件的通訊

ng2 在無關組件的處理上,真的處理得很乾脆,給你一個鉤子,你用吧!就是這種簡單的思路。這裏我只介紹部分,由於官方文檔有更加詳細的介紹,否則我這篇文章就寫得太長了~由於方式有不少種,發揮小聰明就能發現不少。

  • 事件回調傳來傳去的方式

  • Service 的注入

  • # 鉤子的方式

這裏介紹的是一個 # 鉤子的方式來作,直接來代碼吧,很方便的。
其中,須要注意的是做用域的隔離,子組件能夠很好的隔離做用域。

// Parent component
import { Component, OnInit } from '@angular/core';
    
@Component({
    selector: 'app-parent',
    templateUrl: './parent.component.html',
    styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
    
    babyName: string = '小擼一號';
    
    constructor() { }
    
    ngOnInit() {
    }
    
}
// Parent html
<input [(ngModel)]="babyName" type="text">
    
<app-child #child [childName]="babyName"></app-child>
<app-otherChild helloBaby="child.childName"></app-otherChild>
// Child component
import { Component, OnInit, Input } from '@angular/core';
    
@Component({
    selector: 'app-child',
    templateUrl: './child.component.html',
    styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
    
    @Input() childName: string;
    
    constructor() { }
    
    ngOnInit() {
    }
    
}
<h3 style="color:red;">Child:{{childName}}</h3>
// OtherChild component
import { Component, OnInit, Input } from '@angular/core';
    
@Component({
    selector: 'app-otherChild',
    templateUrl: './otherChild.component.html',
    styleUrls: ['./otherChild.component.css']
})
export class OtherChildComponent implements OnInit {
    
    @Input() helloBaby: string;
    
    constructor() { }
    
    ngOnInit() {
    }
    
    changeChildName(e) {
        this.helloBaby = '小擼新號';
    }
}
// OtherChild html
<h3 style="color:blue;">otherChild:{{helloBaby}}</h3>
<button (click)="changeChildName($event)">我來統一修改一下</button>

其實還有一些方式和特殊場景下的處理,因此整體來講,ng2 在這方面是不錯的~

相關文章
相關標籤/搜索