angular1與react生命週期對比

可否理解一個組件的生命週期是很是重要的,甚至能夠說是最重要的內容,他是一切進階的基石,下面咱們就從angular1的生命週期開始吧。html

angular1生命週期

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生命週期

react的生命週期分爲三大階段,git

  • 插入dom(mount)
  • 從新render(update)
  • 銷燬dom(unmount)

在定義class(組件)的時候其實就是在定義一個狀態機,定義了各類狀態的響應,這裏包括這三大階段的鉤子以及事件響應,等待觸發條件的知足。github

1 插入dom(mount)算法

先來講下第一階段,首次render觸發時會執行如下鉤子函數,redux

  • getDefaultProps
    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這樣的屬性指令來作模版輸出控制,該指令會在當前指令做用域下再建立一個子做用域,這使得咱們在獲取子組件的實例的時候會比較麻煩,ngRepeatngSwitch都是這樣,angular1的初衷是不但願咱們本身作字符串拼接,的確就算咱們能拿到$scope,字符串拼接也實在不夠優雅。
    因此render函數直白點完成了兩件事情:函數

    • 執行jsx表達式,生成最終插入dom容器節點的真實dom(這裏不考慮虛擬dom的問題)
    • 藉助react提供的synthetic event system完成事件監聽綁定

    全部葉子組件的jsx模版都是由基礎原生html標籤、屬性以及react所提供的代理屬性組成的,所以若是你寫以下一段模版代碼:

    render(){
      return (
          <div num=1 changehandler={this.changeHandler.bind(this)}/> ) }複製代碼

    numchangehandler屬性會直接被忽略,若是你想在原生標籤上使用自定義屬性,請在屬性前面添加data-

  • componentDidMount

    componentDidMount和angular中的link或postLink很類似,可是它更讓人放心,由於angular中若是你想在link中獲取帶有ngIf或ngRepeat的dom是獲取不到的(由於會再transclude一次並等待下次髒數據校驗纔會插入dom,有興趣的同窗能夠移步重複transcludengIf髒數據校驗),所以在這裏你能夠放心的訪問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變動

狀態變動會觸發如下幾個鉤子

  • shoudComponentUpdate
    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作詳細講解。

文中若有錯誤請你們及時糾正,謝謝。

相關文章
相關標籤/搜索