當前位置:
首頁 > 科技 > Angular組件間通信

Angular組件間通信

前言

史上第一篇在前端早讀課上分享的Angular相關的,今日早讀文章由@Winar_阿進授權分享。

正文從這開始~

核心要點:

由於Angular是基於組件的應用架構,因此可以在組件之間進行進行數據傳遞。

你可以使用@Input()將數據傳遞到子組件中。

你可以使用@Output() 從子組件中獲取數據。

隨著應用變得越來越複雜,父/子組件之間的數據傳遞將會變得越來越困難。

你也可以採用外部數據存儲方案(如ngrx)來構建大型應用程序。

組件是Angular的構建單元。在Angular應用程序中,每一個可視化的元素都由組件構成。基於組件的體系架構最大的優點就是可拆分,就像JavaScript中的函數一樣,如果一個函數太複雜或承擔了過多的職責,那麼就可以將其拆分為多個函數,使一個函數只承擔一個職責。

也即是說,當組件被拆分為更小的組件時,必須要保證各組件之間的數據能夠來回傳遞。因此,為了使應用程序中的數據保持同步,正確的使用組件間通信的方法變得至關重要。幸運的是,Angular已經封裝了能夠實現組件間通信的方法。

當然也可以在根組件—AppComponent下構建整個應用,但如果這麼做的話,AppComponent將會承擔過多的職責。在基於組件的應用架構中,能夠將複雜的組件拆分為承擔單一職責的組件已然成為了一種最佳實踐。

傳遞數據到子組件

在Angular中,使用@Input將父組件的數據傳遞給子組件。假設我們正在構建一個展示所有評論的應用,AppComponent將負責載入所有的評論數據,然後再將每一條評論的數據分別發送給子組件—Comment組件中。

通過@Input() comment將comment參數傳遞到子組件中。以下是整個組件的代碼:

@Component({

selector: comment ,

templateUrl: ./comment.component.html ,

styleUrls:[ ./comment.component.css ]

})

exportclassCommentComponent{

@Input()comment;

}

現在就可以在代碼的其他部分調用Comment組件,並傳遞它所期望接收的評論數據了。調用組件的代碼如下:

理解語法

首先,可以看到一個組件的自定義標籤:。如果你之前用過Angular的話,這些看起來就會很熟悉了。

接下來是使用[comment]進行數據綁定。剛開始看到屬性外面的中括弧,可能有會些困惑;但事實上,在數據傳遞中,中括弧也並不是必須加的,如果不加中括弧數據傳遞的話,則只會傳遞一個字元串到子組件的@Input()中。中括弧的目的是為了告訴Angular這是一個屬性綁定,並且值是動態傳輸的,因此Angular會動態的插入並傳遞數據到子組件中,而不僅僅只傳遞字元串。

最後,通過綁定comment屬性,就獲取了評論的值。Angular就會在當前組件中尋找this.comment屬性的值,並將其傳入到子組件-Comment組件中。

概念的組合

為了展示如下圖所示的評論列表,可以將一些Angular中的概念組合起來使用,包括*ngFor。假設該實例已經載入了評論數據,它將作為組件類中的一部分,並且可以通過this.comments屬性進行調用。

*ngFor="let comment of comments"

[comment]="comment">

最終的渲染結果如下圖所示:

使用了Comment組件的評論列表

捕獲子組件事件

現在我們已經知道如何將評論傳遞到Comment組件中,但如果一個評論被刪除了,該怎樣將它從整個評論列表中移除呢?這會是非常棘手的事情,因為評論數據是保存在Comment組件的父組件—AppComponent中的。

使用@Output()是解決上述問題的一種方法,它可以利用EventEmitter幫助子組件觸發能夠被父組件捕獲的事件。

要使子組件和父組件通信,首先要使用@Output()裝飾器為子組件添加一個新的類屬性。

如上述Comment組件的代碼片段所示,當點擊刪除按鈕的時候,就會調用deleteComment()方法,並且也做好了捕獲來自父組件響應事件的準備。

Delete

從父組件中捕獲事件

在根組件—AppComponent組件中,需要一個新的方法來處理刪除評論的行為。

@Component({

selector: app-root ,

templateUrl: ./app.component.html

})

exportclassAppComponent{

/**[code omitted]**/

onCommentDelete(comment){

// logic to remove comment from comments array

}

}

在視圖層,僅僅需要告訴Angular當onDelete事件被觸發時,立即調用onCommentDelete()方法即可。

*ngFor="let comment of comments"

[comment]="comment"

(onDelete)="onCommentDelete($event)">

如下圖所示就是該應用完成刪除功能之後的樣子:

現在有了Angular的@Output()裝飾器,就能夠刪除評論了。

另外一種獲取數據的方式

到目前為止,我們僅知道了如何在父/子組件之間進行通信。儘管這種方法已經能夠滿足大多數的需求,但隨著應用規模的增長,維護父/子組件間的通信也變得越來越複雜。對於大型應用,使用數據存儲(data store)來減少單個組件的工作量是有效的方案。數據存儲是一個中心存儲的方案,它可以在每一個組件需要數據時就調用一部分數據給該組件使用。每一個組件可以在數據存儲中訂閱他們所需要的數據,而不用手動的將數據傳遞到子組件,以此來減少父/子組件中來回傳遞數據的壓力。

如果你熟悉React的話,那麼這正是Redux解決的問題。在Angular中,可以使用ngrx庫來解決,這個庫也是受到了Redux的啟發。但這兩個庫還有很多關鍵的區別:類型和可觀察對象(observables)。ngrx庫嚴重依賴TypeScript的生態系統,因此會比Redux更加繁重一點,但是卻很容易調試和進行問題的追蹤。

當使用ngrx時,數據的狀態是單個不可變的數據結構。為了改變數據的狀態,可以使用行為的方式來調用函數。這些行為同時又會反過來告訴reducers,哪些是純函數,哪些數據狀態可改變。通過這種方式,應用就可以擁有新的數據狀態了,而訂閱這些數據的組件也可以立即收到新的數據。當組件收到新的數據時,它們會立即重新渲染,以時刻保持視圖層的數據和數據存儲中的數據相同。

這樣做對於開發又意味著什麼呢?

雖然在概念上能夠直接將外部數據傳遞到組件中,而不用通過父子關係來傳遞,但這樣做對於項目的開發到底意為著什麼呢?

假設想在兩個不同的地方展示評論數怎麼辦?如果僅僅依賴組件層級間的數據傳遞會很複雜,因此這也就是中心存儲ngrx的意義所在。

在許多大型應用中,直接向組件傳遞數據在許多方面都是很有用的。由於組件需要處理越來越多的任務,且再添加額外的任務(像『持續追蹤傳遞到子組件的數據』這樣的任務)也變得很複雜。如果不能把傳輸數據的負擔交給外部的數據存儲,那麼當你維護大型Angular應用程序時,可就得時刻小心了。

在上面的例子里,一個外部數據存儲(未在圖中畫出)可以用來把信息傳給SidebarComponent,表示有多少條評論可用——「有兩條評論」,同時還把具體的評論內容發給CommentList組件。這些數據完全繞過了父組件AppComponent。

快速回顧一下Angular的組件通信機制

通過上邊這些內容,已經對Angular的組件之間如何通信有了一些了解。知道了怎樣把數據從一個父組件傳入一個子組件,也知道了怎麼使用Angular中的@Input()裝飾器。

也知道了怎樣使用@Output()裝飾器,以及如何使用EventEmitter把數據從一個子組件發回給一個父組件。

除此之外,當應用程序規模不斷增長的時候,就可以採用ngrx來減輕父子組件之間的壓力。通過使用一個單獨的數據存儲,就可以讓各個組件自己獲取數據,而不必通過多層子組件把數據傳到最終的目標。這就使大規模應用程序的維護變得容易多了。這些原理同樣適用於React之類的庫,他們也用非常類似的辦法解決了相同的問題。

你可以在這個鏈接上看到該系統的演示程序,相應的代碼也可以在這裡下載到。

如何進一步學習

建議大家可以再看看 Angular關於組件交互的文檔,進一步了解底層機制,以及隨著框架的快速演進時,最新的語法和最佳實踐。

最後,你也可以再讀讀ngrx官方網站上的ngrx文檔,或者也推薦看看我用ngrx構建的示常式序。

最後,對ng有興趣的,可以看看今年剛出版的這本【圖書】Angular權威教程

關於本文

作者:@Winar_阿進

原文:http://xujin.pro/2017-05-26-angular-component-communication.html

點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 前端早讀課 的精彩文章:

JavaScript函數的多種寫法
讀前端架構設計——我眼中的前端架構
你不懂JS:ES6與未來 新增API
代碼審查應該關注什麼:性能
域名劫持資源重載入方案

TAG:前端早讀課 |

您可能感興趣

乾貨 Angular組件測試
Angular 6 LazyLoading 變化
容器化分散式日誌組件ExceptionLess的Angular前端UI
Promise介面是AngularJS組織API的基礎
AngularJS篇 1.AngularJS不入門
Angular.js 發布,Web 前端框架
前端基於angular6的ionic3,後端基於springmvc post get請求實現
Angular、React 當前,Vue.js 優劣幾何?
Vue.js 為何能逆襲 Angular 和 React 而主導前端?
Angular 6 正式發布:統一框架、Material和CLI 三大模塊
Google的Angular 迫使我放棄了 Web 開發
Angular和Vue.js 深度對比
使用 Angular CLI 搭建項目
angularjs 點擊div外面,隱藏該div
Angular 8正式發布!
AngularJS中的MVC模式
Web 前端框架 Angular 發布 7.0 首個 beta 版
使用 Angular 5.0和Spring Boot 2.0 構建一個基本的 CRUD 應用
如何用Angular5創建一個PWA項目
前端圈小可愛Vue的自白:我年少成名卻又屢陷React、Angular混戰