天天看點

2. React.Component class元件的生命周期API定義class元件class元件的生命周期-分為3大部分

class式元件的生命周期API

  • 定義class元件
  • class元件的生命周期-分為3大部分
    • 挂載 -> (Mount):元件第一次在DOM樹中渲染
      • 1.constructor(props)
      • 2.render()
      • 3.componentDidMount()
    • 更新 -> (update):元件更新,重新渲染
          • 1.static getDerivedStateFromProps(props, state) 不常用
          • 2.shouldComponentUpdate(nextProps, nextState) 不常用
          • 3.getSnapshotBeforeUpdate(prevProps, prevState)不常用
      • 4.componentDidUpdate(prevProps,prevState,snapshot)
    • 解除安裝 ->(Unmount):元件從DOM樹中删除
      • 1.componentWillUnmount()

定義class元件

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
           

1.需繼承React.component

2.在 React.Component 的子類中有個必須定義的 render() 函數

class元件的生命周期-分為3大部分

下面常用的生命周期方法會被加粗。其餘生命周期函數的使用則相對罕見。

挂載 -> (Mount):元件第一次在DOM樹中渲染

當元件執行個體被建立并插入 DOM 中時,其生命周期調用順序如下:

  1. constructor(): 在 React 元件挂載之前,會調用它的構造函數
  2. static getDerivedStateFromProps()
  3. render():React渲染
  4. componentDidMount(): 在元件挂載後(插入 DOM 樹中)立即調用。

1.constructor(props)

我們把元件渲染,并且構造DOM元素插入到頁面的過程稱為元件的挂載

在 React 元件挂載之前,會調用它的構造函數。在為 React.Component 子類實作構造函數時,在其他語句之前前調用 super(props)。否則,this.props 在構造函數中可能會出現未定義的 bug。

通常,react中,構造函數僅用于一下兩種情況

1.給this.state 指派對象初始化内部state (初始化state值)

2.為事件處理函數綁定執行個體

如果不初始化state或不進行方法綁定,則不需要為React元件實作構造函數

注意:

  • 在constructor()函數中不要調用setState()方法,可直接為this.state賦初始值state
  • 也隻能在構造函數中直接為this.state指派,其他方法中指派應使用this.setState()
  • 要避免在構造函數中引入任何副作用或訂閱。如遇到此場景,請将對應的操作放置在 componentDidMount 中。
constructor(props){
	super(props);
	//不要在這裡調用 this.setState()
	this.state = {counter:0};
	this.handleClick = this.handleClick.bind(this)
}
           

避免将 props 的值複制給 state!這是一個常見的錯誤:

constructor(props) {

super(props);

// 不要這樣做

this.state = { color: props.color };

}

如此做毫無必要(你可以直接使用 this.props.color),同時還産生了 bug (更新 prop 中的 color 時,并不會影響 state)。

隻有在你刻意忽略 prop 更新的情況下使用。此時,應将 prop 重命名為 initialColor 或 defaultColor。必要時,你可以修改它的 key,以強制“重置”其内部 state。

2.render()

render()方法是class元件中唯一必須實作的方法

1.初始化:React在應用初始化的時候,會渲染全部元件

2.setState()在任何情況下都會導緻元件的重新渲染,即使state未發生變化

當一個元件調用了setState()函數時,不論state是否發生了變化,該元件都将被重新渲染。

3.隻要父元件重新渲染了,那麼子元件就會重新渲染。即使元件未發生變化,并且從父元件接收的props也沒有發生變化,但是隻要父元件重新渲染了,那麼子元件就會重渲染。

當render被調用時,它會檢查this.props和this.state的變化并傳回一下類型之一

  • React元素: JSX/自定義元件
  • 數組或fragments:一個元件傳回多個元素
render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}
           
  • Portals:将子節點渲染到存在于父元件以外的 DOM 節點的優秀的方案
  • 字元串或數值類型:在DOM中被渲染為文本節點
  • 布爾類型或 null:什麼都不渲染

render() 函數應該為純函數,這意味着在不修改元件 state 的情況下,每次調用時都傳回相同的結果,并且它不會直接與浏覽器互動。

如需與浏覽器進行互動,請在 componentDidMount() 或其他生命周期方法中執行你的操作

注意:

如果 shouldComponentUpdate() 傳回 false,則不會調用 render()。

React的元件重渲染機制,是一個嚴謹的做法,因為它避免了,狀态更新後,手動去重渲染相關元件的操作。但是有些時候我們更新了某個元件的資料,但是并不想讓與其相關的其他元件被重渲染,因為反複的重渲染未變化的元件,既耗時也會影響性能,此時就需要對React的重渲染進行優化

3.componentDidMount()

componentDidMount() 會在元件挂載後(插入 DOM 樹中)立即調用。

依賴于 DOM 節點的初始化應該放在這裡。

如需通過網絡請求擷取資料,此處是執行個體化請求的好地方。

這個方法是比較适合添加訂閱的地方。如果添加了訂閱,請不要忘記在 componentWillUnmount() 裡取消訂閱(釋出類似觸發事件,訂閱類似監聽事件)

可以在 componentDidMount() 裡直接調用 setState()。它将觸發額外渲染,但此渲染會發生在浏覽器更新螢幕之前。如此保證了即使在 render() 兩次調用的情況下,使用者也不會看到中間狀态。請謹慎使用該模式,因為它會導緻性能問題。通常,你應該在 constructor() 中初始化 state。如果你的渲染依賴于 DOM 節點的大小或位置,比如實作 modals 和 tooltips 等情況下,你可以使用此方式處理

更新 -> (update):元件更新,重新渲染

  1. static getDerivedStateFromProps() :不常用 擷取派生狀态
  2. shouldComponentUpdate():偶爾用 當傳回值為 false,則不會調用 componentDidUpdate()和render()。
  3. render()
  4. getSnapshotBeforeUpdate(): 不常用 擷取更新前快照
  5. componentDidUpdate():更新後會立即調用
元件更新相關函數,在元件初始挂載的時候都不會調用。
1.static getDerivedStateFromProps(props, state) 不常用

在調用 render 方法之前調用,并且在初始挂載及後續更新時都會被調用。它應傳回一個對象來更新 state,如果傳回 null 則不更新任何内容。

此方法無權通路元件執行個體

2.shouldComponentUpdate(nextProps, nextState) 不常用

在元件接收到新的props或state時調用,通過傳回值來确定是否重新渲染目前元件

預設行為是 state 每次發生變化元件都會重新渲染。

當 props 或 state 發生變化時,shouldComponentUpdate() 會在渲染render執行之前被調用。傳回值預設為 true。首次渲染或使用 forceUpdate() 時不會調用該方法。

此方法僅作為性能優化的方式而存在。不要企圖依靠此方法來“阻止”渲染,因為這可能會産生 bug。

一定要手動編寫此函數,可以将 this.props 與 nextProps 以及 this.state 與nextState 進行比較,并傳回 false 以告知 React 可以跳過更新。

請注意,傳回 false 并不會阻止子元件在 state 更改時重新渲染。

不建議在 shouldComponentUpdate() 中進行深層比較或使用

JSON.stringify()。這樣非常影響效率,且會損害性能。

目前,如果 shouldComponentUpdate() 傳回 false,則不會調用 UNSAFE_componentWillUpdate(),render() 和 componentDidUpdate()
3.getSnapshotBeforeUpdate(prevProps, prevState)不常用

最近一次渲染輸出(送出到 DOM 節點)之前調用。它使得元件能在發生更改之前從 DOM 中捕獲一些資訊(例如,滾動位置)。此生命周期方法的任何傳回值将作為參數傳遞給 componentDidUpdate()。

此用法并不常見,但它可能出現在 UI 進行中,如需要以特殊方式處理滾動位置的聊天線程等。

4.componentDidUpdate(prevProps,prevState,snapshot)

componentDidUpdate() 在更新後會立即調用,首次渲染不會執行該方法,元件更新,重渲染完畢後調用,prevProps 和prevState ,分别表示元件更新前的props和state

當元件更新後,可以在此處對 DOM 進行操作。如果你對更新前後的 props 進行了比較,也可以選擇在此處進行網絡請求。(例如,當 props 未發生變化時,則不會執行網絡請求)。

componentDidUpdate(prevProps){
	//典型用法 (不要忘了比較props):
	if(this.props.userID !== prevProps.userID){
		this.fetchData(this.props.userID)
	}
}
           

可以在 componentDidUpdate() 中直接調用 setState(),但請注意它必須被包裹在一個條件語句裡,正如上述的例子那樣進行處理,否則會導緻死循環。

它還會導緻額外的重新渲染,雖然使用者不可見,但會影響元件性能。

如果元件實作了 getSnapshotBeforeUpdate() 生命周期(不常用),則它的傳回值将作為 componentDidUpdate() 的第三個參數 “snapshot” 參數傳遞。否則此參數将為 undefined。

注意:

如果 shouldComponentUpdate() 傳回值為 false,則不會調用 componentDidUpdate()

解除安裝 ->(Unmount):元件從DOM樹中删除

當元件從 DOM 中移除時會調用如下方法:

componentWillUnmount():元件解除安裝及銷毀之前直接調用

1.componentWillUnmount()

componentWillUnmount() 會在元件解除安裝及銷毀之前直接調用。在此方法中執行必要的清理操作,例如,清除 timer,取消網絡請求或清除在 componentDidMount() 中建立的訂閱等

componentWillUnmount() 中不應調用 setState(),因為該元件将永遠不會重新渲染。元件執行個體解除安裝後,将永遠不會再挂載它。
2. React.Component class元件的生命周期API定義class元件class元件的生命周期-分為3大部分
2. React.Component class元件的生命周期API定義class元件class元件的生命周期-分為3大部分