React生命週期以及注意事項

react快速入門react

react組件的生命週期

在組件的整個生命週期中,隨着該組件的props或者state發生改變,其DOM表現也會有相應的變化git

State 是一種數據結構,用於組件掛載時所需數據的默認值。State 可能會隨着時間的推移而發生突變,但多數時候是做爲用戶事件行爲的結果。 Props(properties 的簡寫)則是組件的配置。props 由父組件傳遞給子組件,而且就子組件而言,props 是不可變的(immutable)。組件不能改變自身的 props,可是能夠把其子組件的 props 放在一塊兒(統一管理)。Props 也不只僅是數據--回調函數也能夠經過 props 傳遞。github

組件的生命主要包括3個階段: 掛載、更新、卸載,React 16開始還添加了錯誤處理。算法

韋博青少微信端用的是react15版本的,先簡述下15版本的生命週期,react16的生命週期也是基於15上修改數組

react生命週期

第一個是組件初始化(initialization)階段

import React, { Component } from 'react';

class Test extends Component {
  constructor(props) {
    super(props);
  }
}
複製代碼

構造方法(constructor() ),Test類繼承了react Component這個基類,也就繼承這個react的基類,纔能有render(),生命週期等方法可使用 super(props)用來調用基類的構造方法( constructor() ), 也將父組件的props注入給子組件,供子組件讀取(組件中props只讀不可變,state可變) 而constructor()用來作一些組件的初始化工做,如定義this.state的初始內容。安全

第二個是組件的掛載(Mounting)階段

此階段分爲componentWillMount,render,componentDidMount三個時期 componentWillMount: 在組件掛載到DOM前調用,且只會被調用一次,在這邊調用this.setState不會引發組件從新渲染,也能夠把寫在這邊的內容提早到constructor()中,因此項目中不多用。 render: 根據組件的props和state(無二者的重傳遞和重賦值,論值是否有變化,均可以引發組件從新render) ,return 一個React元素(描述組件,即UI),不負責組件實際渲染工做,以後由React自身根據此元素去渲染出頁面DOM。render是純函數(Pure function:函數的返回結果只依賴於它的參數;函數執行過程裏面沒有反作用),不能在裏面執行this.setState,會有改變組件狀態的反作用。微信

componentDidMount: 組件掛載到DOM後調用,且只會被調用一次 1.在componentDidMount請求異步加載的數據 2.添加事件監聽 — Adding event listeners (or subscriptions)數據結構

第三個是組件的更新(update)階段

在講述此階段前須要先明確下react組件更新機制dom

  1. 父組件從新render引發的props更新,更新後的state和props相對以前不管是否有變化,都將引發子組件的從新render
  2. setState引發的state更新,可經過shouldComponentUpdate方法優化。
class Child extends Component {
   constructor(props) {
        super(props);
        this.state = {
          someThings:1
        }
   }
 
   handleClick = () => { // 雖然調用了setState ,但state並沒有變化
        const preSomeThings = this.state.someThings
         this.setState({
            someThings: preSomeThings
         })
   }
   shouldComponentUpdate(nextStates){ // 應該使用這個方法,不然不管state是否有變化都將會致使組件從新渲染
        if(nextStates.someThings === this.state.someThings){
          return false
        }
    }
    render() {
        return <div onClick = {this.handleClick}>{this.state.someThings}</div>
    }
}
複製代碼

componentWillReceiveProps(nextProps) 此方法只調用於props引發的組件更新過程當中,參數nextProps是父組件傳給當前組件的新props。但父組件render方法的調用不能保證重傳給當前組件的props是有變化的,因此在此方法中根據nextProps和this.props來查明重傳的props是否改變,以及若是改變了要執行啥,好比根據新的props調用this.setState出發當前組件的從新render異步

shouldComponentUpdate(nextProps, nextState)

此方法經過比較nextProps,nextState及當前組件的this.props,this.state,返回true時當前組件將繼續執行更新過程,返回false則當前組件更新中止,以此可用來減小組件的沒必要要渲染,優化組件性能。 ps:這邊也能夠看出,就算componentWillReceiveProps()中執行了this.setState,更新了state,但在render前(如shouldComponentUpdate,componentWillUpdate),this.state依然指向更新前的state,否則nextState及當前組件的this.state的對比就一直是true了。

componentWillUpdate(nextProps, nextState)

此方法在調用render方法前執行,在這邊可執行一些組件更新發生前的工做,通常較少用。

render

render方法在上文講過,這邊只是從新調用。

componentDidUpdate(prevProps, prevState)

此方法在組件更新後被調用,能夠操做組件更新的DOM,prevProps和prevState這兩個參數指的是組件更新前的props和state

卸載階段

此階段只有一個生命週期方法:componentWillUnmount componentWillUnmount 此方法在組件被卸載前調用,能夠在這裏執行一些清理工做,好比清除定時器,清除componentDidMount中手動建立的DOM元素等,以免引發內存泄漏。

react16 生命週期函數作的更改

舊的生命週期十分完整,基本能夠捕捉到組件更新的每個state/props/ref,沒有什麼邏輯上的毛病。

可是架不住官方本身搞事情,react打算在17版本推出新的Async Rendering,提出一種可被打斷的生命週期,而能夠被打斷的階段正是實際dom掛載以前的虛擬dom構建階段,也就是要被去掉的三個生命週期。

生命週期一旦被打斷,下次恢復的時候又會再跑一次以前的生命週期, 所以componentWillMount,componentWillReceiveProps, componentWillUpdate都不能保證只在掛載/拿到props/狀態變化的時候刷新一次了,因此這三個方法被標記爲不安全。

兩個新生命週期

static getDerivedStateFromProps 觸發時間:在組件構建以後(虛擬dom以後,實際dom掛載以前) ,以及每次獲取新的props以後。 每次接收新的props以後都會返回一個對象做爲新的state,返回null則說明不須要更新state. 配合componentDidUpdate,能夠覆蓋componentWillReceiveProps的全部用法

class Example extends React.Component {
  static getDerivedStateFromProps(nextProps, prevState) {
    // 沒錯,這是一個static
  }
}

複製代碼

getSnapshotBeforeUpdate 觸發時間: update發生的時候,在render以後,在組件dom渲染以前。 返回一個值,做爲componentDidUpdate的第三個參數。 配合componentDidUpdate, 能夠覆蓋componentWillUpdate的全部用法。

react錯誤處理
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  componentDidCatch(error, info) {
    // Display fallback UI
    this.setState({ hasError: true });
    // You can also log the error to an error reporting service
    logErrorToMyService(error, info);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}
複製代碼

setState方法多是同步的,也多是異步的

由 React 控制的事件處理過程 setState 不會同步更新 this.state

基於性能考慮,React 一般是批量合併更新,調用 setState() 以後,this.state 並無立刻修改,而是建立了一箇中間態做爲過渡。

可是有些例外狀況,它是同步執行的,好比:eventListeners,Ajax,setTimeout 等。 緣由是這些 JS 原生的 API 不在 React 的上下文控制範圍,沒法進行優化。

this.setState(
  { count: 1 }, () => {
      console.log(this.state.count)//輸出count=1
  }
)

複製代碼

react事件綁定

因爲類的方法默認不會綁定this,所以在調用的時候若是忘記綁定,this的值將會是undefined。 一般若是不是直接調用,應該爲方法綁定this。綁定方式有如下幾種:

  1. 在構造函數中使用bind綁定this
class Button extends React.Component {
constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick(){
    console.log('this is:', this);
  }
  render() {
    return (
      <button onClick={this.handleClick}> Click me </button>
    );
  }
}
複製代碼
  1. 在調用的時候使用bind綁定this
class Button extends React.Component {
  handleClick(){
    console.log('this is:', this);
  }
  render() {
    return (
      <button onClick={this.handleClick.bind(this)}> Click me </button>
    );
  }
}
複製代碼
  1. 在調用的時候使用箭頭函數綁定this
class Button extends React.Component {
  handleClick(){
    console.log('this is:', this);
  }
  render() {
    return (
      <button onClick={()=>this.handleClick()}> Click me </button>
    );
  }
}
複製代碼
  1. 使用屬性初始化器語法綁定this(實驗性)
class Button extends React.Component {
  handleClick=()=>{
    console.log('this is:', this);
  }
  render() {
    return (
      <button onClick={this.handleClick}> Click me </button>
    );
  }
}
複製代碼

方式1是官方推薦的綁定方式,也是性能最好的方式。方式2和方式3會有性能影響而且當方法做爲屬性傳遞給子組件的時候會引發重渲問題。方式4目前屬於實驗性語法,可是是最好的綁定方式,須要結合bable轉譯

react列表渲染時爲何儘可能不要把索引設置爲key值

使用數組下標作key是不被推薦的,若是遇到數組排序的狀況下,將下降渲染性能。

React中的核心概念

  1. 虛擬DOM(Virtual DOM) github.com/livoras/blo…

  2. Diff算法(虛擬DOM的加速器,提高React性能的法寶) github.com/zmmbreeze/b…

公衆號
相關文章
相關標籤/搜索