可否理解一個組件的生命週期是很是重要的,甚至能夠說是最重要的內容,他是一切進階的基石,下面咱們就從angular1的生命週期開始吧。html
angular1的生命週期在1.5以前是很晦澀的,controller、compile、preLink、postLink,compile的return函數。從字面上讓人徹底摸不着頭腦,到了1.5增長了angular.component,這一問題有了很大改觀,生命週期所有放到controller(controller再也不做爲一個生命週期鉤子存在),controller就是一個class,實例函數$onInit、$onPostLink和$onDestroy組成了新的生命週期鉤子,從字面上也容易理解了不少。$onInit表明編譯前,在這裏你能夠對$scope作屬性變動,和邏輯定義;$onPostLink表明編譯後,這個時候子指令已完成了編譯,你能夠在這裏獲取到任意子指令實例並調用其方法;$onDestroy在當前scope被銷燬時調用,在這裏你須要對dom作銷燬,以及可能的全局變量作清空。很簡單就是組件編譯前、組件編譯後和組件銷燬時。那麼咱們再看看react的生命週期鉤子。react
react的生命週期分爲三大階段,git
- 插入dom(mount)
- 從新render(update)
- 銷燬dom(unmount)
在定義class(組件)的時候其實就是在定義一個狀態機,定義了各類狀態的響應,這裏包括這三大階段的鉤子以及事件響應,等待觸發條件的知足。github
1 插入dom(mount)算法
先來講下第一階段,首次render觸發時會執行如下鉤子函數,redux
getDefaultProps: function(){
return { /* 默認屬性 */};
}複製代碼
getInitialState性能優化
getInitialState: function(){
return { /* 初始狀態 */};
}複製代碼
這兩個函數不難理解,目的是使代碼結構更清晰,不須要在constructor裏作過多的打底處理。dom
componentWillMount
這個方法在出現class XX extends React.Component
以後其實就能夠用constructor
來代替了。對於angular1.5這和$onInit
也是相似的,一樣也能夠用constructor代替。異步
render
這個函數其實和angular指令中的template屬性(值對應一個函數)很類似,可是藉助jsx,render比template屬性強大實在太多,angular所提供的template不夠靈活,在template函數中沒法拿到$scope,天然咱們就選擇例如ngIf
這樣的屬性指令來作模版輸出控制,該指令會在當前指令做用域下再建立一個子做用域,這使得咱們在獲取子組件的實例的時候會比較麻煩,ngRepeat
、ngSwitch
都是這樣,angular1的初衷是不但願咱們本身作字符串拼接,的確就算咱們能拿到$scope,字符串拼接也實在不夠優雅。
因此render函數直白點完成了兩件事情:函數
全部葉子組件的jsx模版都是由基礎原生html標籤、屬性以及react所提供的代理屬性組成的,所以若是你寫以下一段模版代碼:
render(){
return (
<div num=1 changehandler={this.changeHandler.bind(this)}/> ) }複製代碼
num
和changehandler
屬性會直接被忽略,若是你想在原生標籤上使用自定義屬性,請在屬性前面添加data-
。
componentDidMount
componentDidMount
和angular中的link或postLink很類似,可是它更讓人放心,由於angular中若是你想在link中獲取帶有ngIf或ngRepeat的dom是獲取不到的(由於會再transclude一次並等待下次髒數據校驗纔會插入dom,有興趣的同窗能夠移步重複transclude和ngIf髒數據校驗),所以在這裏你能夠放心的訪問dom。
小結:上述方法除了render
,只會伴隨第一次render執行一次。
2 從新render
當組件props和state(經過setState)發生變動時,會觸發re-render
操做。所以這裏咱們把state和props變化分開來講。
在angular1中其實並無屢次觸發的鉤子,像前面說到的controller、compile等也都只執行一次,其實react的從新渲染在angular相似$watch,通常咱們在$watch來實現dom的變動,這種命令式的修改dom固然是不推薦的,react採用了一種更完全的方式,給人的感覺就像又走了一遍第一次渲染同樣,而你能夠這樣理解,相對於第一次,它可能僅僅變動了個別state或props,經過虛擬dom和diff算法,react幫助你高效的將變動應用於虛擬dom上最終re-render出新的dom樹。
2.1 state變動
狀態變動會觸發如下幾個鉤子
shouldComponentUpdate: function(nextProps, nextState){
return true
}複製代碼
該函數給用戶一個機會使得其能夠控制是否須要進行從新渲染,angular1並無提供終止指令編譯的鉤子函數,這是react的高級特性了,主要針對性能優化,本身沒有用過就不誤導你們了。componentWillUpdate
componentWillUpdate: function(nextProps, nextState){
// 爲re-render作準備
}複製代碼
爲啥須要這個鉤子呢,由於只有shouldComponentUpdate
返回true才能肯定必定會從新渲染,那麼在這裏咱們能夠對界面的提示UI作變動,好比以前爲了獲取state或props會由於異步請求出現loading,那麼這個時候就能夠隱藏loading。記住這裏不能有任何會再次觸發組件從新渲染的邏輯。
componentDidUpdate
componentDidUpdate: function(prevProps, prevState){
// 能夠訪問渲染完成的dom
}複製代碼
這個沒啥可說的,和componentDidMount
是同樣的。
2.2 props變動
componentWillReceiveProps: function(nextProps) {
this.setState({
// new state
});
}複製代碼
不像state須要調用setState纔會觸發re-render,由父組件致使的任何屬性變動都會觸發re-render,不須要調用額外的方法。其實props變動所經歷的生命週期鉤子和state幾乎同樣,惟一不一樣是在shouldComponentUpdate以前增長了componentWillReceiveProps,用意也十分明顯,咱們能夠在componentWillReceiveProps中經過setState對state作修改,好比組件內部的state是根據某個或多個props計算得出的,這樣咱們在調用setState時候也不會形成額外的re-render被觸發,深刻理解react
3 銷燬dom(unmount)
當咱們改變UI佈局或者使用接口刪除組件樹上某個組件時就會觸發組件的componentWillUnmount
方法,在這裏你能夠取消事件監聽或定時器,以及其餘會形成全局引用的變量。
class App extend Component {
componentWillUnmount(){
// unregister event or clear timer
}
}
render(<App />, document.getElementById('root') function ummount(){ React.unmountComponentAtNode(document.getElementById('root')); }複製代碼
4 結束
這篇其實和angular1的對比不是太多,但其實大概的生命週期和angular1仍是大同小異,特別是re-render這塊更有條理也更有性能優點。react與angular1的對比先暫告一段落,後面將開始redux的學習,同時會對官方的demo作詳細講解。
文中若有錯誤請你們及時糾正,謝謝。