React的生命週期究竟是怎麼一回事?

儘可能全面詳細的整理一下React的生命週期中的知識點。javascript

組件

組件是獨立的封裝的能夠複用的一個小部件,它是React的核心思想之一。經過劃分組件,能夠將一個頁面劃分紅獨立的多個可複用的組件,各個組件經過嵌套、組合造成一個完整的頁面。java

在React中,組件基本由三個部分組成:屬性(props)、狀態(state)以及生命週期方法。能夠將組件簡單地看做一個「狀態機」,根據不一樣的stateprops呈現不一樣的UI,經過與用戶的交互實現不一樣的狀態,而後從新渲染組件,UI能夠跟隨數據變化而變化。react

建立組件

組件常分爲兩種:Class ComponentFunctional Component設計模式

無狀態組件

Functional Component也稱爲無狀態組件,它多用於純展現組件,這種組件只負責根據傳入的props來渲染組件,而不涉及state狀態管理。數組

在大部分React代碼中,大多數組件被寫成無狀態的組件,經過簡單組合能夠構建成其餘的組件等;這種經過多個簡單而後合併成一個大應用的設計模式被提倡。網絡

無狀態組件能夠經過函數形式或者ES6的箭頭函數來建立:異步

// 函數
function HelloFunctional(props){
  return <div>hello {props.name}</div>;
}

// ES6箭頭函數
const HelloFunctional = (props) => (<div>hello {props.name}</div>);

無狀態組件有如下幾個特色:函數

  1. 代碼可讀性更好
  2. 組件不會被實例化,渲染性能提高
  3. 無生命週期方法
  4. 只能輸入props,一樣的輸入必定會有一樣的輸出

因此,在項目中若是不須要進行狀態管理,應該儘可能寫成無狀態組件的形式。性能

有狀態組件

如今主流的建立有狀態組件的形式是經過ES6的Class來建立,取代React.createClassthis

Class HelloClass extends React.Component{
  constructor(){
    this.state = {
      name:'axuebin'
    }
  }
  render(){
    return (<div>hello {this.state.name}</div>);
  }
}

這是最簡潔的一個組件,它須要使用到內部狀態state

當組件須要使用內部狀態時或者須要使用生命週期方法時就須要使用有狀態組件。

組件的生命週期

React組件的生命週期能夠分爲掛載、渲染和卸載這幾個階段,當渲染後的組件更新後,會從新渲染組件,直到卸載。先分階段來看看每一個階段有哪些生命週期函數。

掛載階段(Mounting)

屬於這個階段的生命週期函數有:

  1. constructor()
  2. componentWillMount()
  3. render()
  4. componentDidMount()

constructor()

constructor() {
  super();
  this.state = {name: 'axuebin'};
  this.handleClick = this.handleClick.bind(this); 
}

這個階段就是組件的初始化,constructor()能夠理解爲組件的構造函數,從組件的類class實例化一個組件實例。這個函數是組件造成時就被調用的,是生命週期中最早執行的。

constructor()函數內,首先必須執行super(),不然this.props將是未定義,會引起異常。

而後,若是有必要,能夠進行:

  • state的初始化
  • 方法的綁定

若是不須要這兩步,能夠直接省略constructor函數。

componentWillMount()

這個函數按照駝峯法的命名規則能夠理解爲「組件即將被掛載」,因此這個函數是組件首次渲染(render)前調用的。

在每次頁面加載、刷新時,或者某個組件第一次展示時都會調用這個函數。一般地,咱們推薦使用constructor()來替代。

注意:在這個函數中,不能夠調用setState來修改狀態。

render()

render() {
  return(
    <div>hello {this.state.name} {this.props.age}</div>
  )
}

render()在生命週期中是必須的,是渲染組件用的。

當這個函數被調用時,須要檢查this.propsthis.state而且返回一個元素(有且只有一個元素),這個元素多是一個原生DOM元素,也有多是另外一個React組件。

能夠在stateprops狀態爲空時試着返回一個null或者false來聲明不想渲染任何東西。

在這個函數中,不該該改變組件的狀態,也就是不執行this.setState,須要保持render()函數的純淨。

在這個函數中,能夠對props進行調用並組合,但不可修改。

componentDidMount()

componentDidMount() {
  this.setState({name:'xb'});
}

這個函數在組件加載渲染完成後當即調用,此時頁面上已經渲染出真實的DOM了,能夠在這個函數中訪問到真實的DOM(能夠經過this.refs來訪問真實DOM)。

在這個階段,還能夠作一件事,能夠修改state了!!!

並且,異步獲取數據在這個階段執行也是比較合理的,獲取數據以後setState,而後從新渲染組件。

更新階段(Updating)

屬性或狀態的改變會觸發一次更新。當一個組件在被從新渲染時,這些方法將會被調用:

  1. componentWillReceiveProps()
  2. shouldComponentUpdate()
  3. componentWillUpdate()
  4. render()
  5. componentDidUpdate()

componentWillReceiveProps()

已加載的組件在props發生變化時調用,若須要更新狀態,可能須要對比this.propsnextProps而後在該方法中使用this.setState來處理狀態的改變。

須要注意的是,有些狀況下,即便props未改變也會觸發該函數,因此必定要先比較this.propsnextProps再作操做。

該函數只監聽props的改變,this.setState不會觸發這個函數。

componentWillReceiveProps(nextProps){
  if (this.props.color !== nextProps.color){
    this.setState({});
  }
}

shouldComponentUpdate()

這個函數只返回truefalse,表示組件是否須要更新(從新渲染)。

  1. 返回true就是緊接着如下的生命週期函數;
  2. 返回false表示組件不須要從新渲染,再也不執行任何生命週期函數(包括render)。

這個函數使用需謹慎,react官方文檔中說道,在將來這個函數返回false可能仍然使得組件從新渲染。

componentWillUpdate()

這個函數看名字就和componentWillMount很像,它執行的階段也很像。在接收到新的props或者state以後,這個函數就會在render前被調用。

一樣的,在這個函數中不能使用this.setState()。若是須要更新狀態,請在componentWillReceiveProps中調用this.setState()

render()

又是一次的render。這和掛載階段的render有什麼區別呢?

在函數的性質上來講,二者毫無區別,只不過是在生命週期的不一樣階段的調用。

  • 前一個render是在組件第一次加載時調用的,也就是初次渲染,能夠理解爲mount
  • 後一個render是除去第一次以後調用的,也就是再渲染,re-render

componentDidUpdate()

一樣地,這個方法是在組件re-render以後調用的,該方法不會在初始化的時候調用。和componentDidMount同樣,在這個函數中可使用this.refs獲取真實DOM。

還能夠修改state哦,不過會致使組件再次re-render

卸載階段(Unmounting)

該方法將會在 component 從DOM中移除時調用

  • componentWillUnmount()

componentWillUnmount()

卸載階段就很簡單了,就這一個生命週期函數,在組件被卸載和銷燬以前馬上調用。

在這個函數中,應該處理任何須要的清理工做,好比銷燬定時器、取消網絡請求、清除以前建立的相關DOM節點等。

生命週期流程圖

原文地址:http://axuebin.com/blog/2017/...

相關文章
相關標籤/搜索