如下的測試例子均可以在 github 找到,可是最近好像不太穩定。javascript
其實 ng2 在這方面作得挺好的,用起來也很簡單,因此看完基本就能夠動手寫一寫。強大並不止是這一方面,在寫這些的過程當中,經過一些配置,讓開發很純粹,有時間再錄一個新手入門的開發教程。css
這種方式是最簡單的,在 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()
方法。
從軟件的結構上來說,是上層抽象對底層的具體實現是隱藏的,因此具體層的東西最好儘量少的知道抽象層的事情,也許表達方式不同,可是這樣的話封閉性會好不少,更多的暴露是以某一個權限開放的接口形式。可是通訊是很複雜的東西,就好像人與人之間的聯繫是同樣的。好吧,咱們來具體說一會兒組件怎麼訪問父組件。主要經過的方式是:
在子組件定義一個 @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 類型的數據,因此傳入後定義接口的參數類型也是相對應的。
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 在這方面是不錯的~