關於 React 組件生命週期
前言
最近因為需要,主要是為暑假的實習做準備,所以開始學習 React,其實還只是很菜很菜的,所以覺得應該要好好扎實的學,不要再像之前一樣,又因為基礎不扎實導致後續很多開發上的問題。這篇要來介紹 React 組建的生命週期,之前如果有用過 Vue 的話就會知道 Vue 也是有組建的生命週期的,之前我也寫過一篇,可以參考 關於 Vue 的生命週期與鉤子函數。話不多說,進入正題吧!
參考
參考 | 鏈接 |
---|---|
理解React组件生命周期 | https://segmentfault.com/a/1190000013309058 |
React函数组件和类组件的区别 | https://blog.csdn.net/wu_xianqiang/article/details/91320529 |
正文
React 的生命週期大致上可以分為三個階段:
- 初始化
- 更新
- 卸載
直接來看看 React 完整的生命週期圖:
看不懂也沒關係,接下來會做更詳細的解釋。
組件初始化(initial)
constructor()
React 組件的構造函數會在渲染前被調用。當我們為一個 React.Component
子類定義構造函數時,好習慣是在任何其他表達是之前先調用 super(props)
,否則 this.props
在組件內將會是 undefined。
構造函數是初始化狀態的合適位置,如果不初始化狀態或是不綁定方法,那其實也就不需要構造函數了。所以通常好習慣就是在創建一個組件時記得都要加上 constructor
,並且記得要 super(props)
,這樣才能調用父類的構造函數,然後如果有要定義、初始化的狀態也是在這邊定義。
看看下面例子:
class Counter extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
}
}
componentWillMount()
componentWillMount()
componentWillMount()
其實在實際項目中用得很少,其實所做的事情也可以由 constructor()
完成,所以通常都推薦用 constructor()
就好,因此這邊就不對這個鉤子做太多深入。
render()
render() {
return (
/* jsx */
)
}
render()
是必須的。render()
方法要求要返回一個 jsx 元素,只能ㄧ個!必須要用一個外層的 jsx 包裹其他 jsx 元素,返回多個並列的 jsx 元素是不合法的。
render()
應該保持純淨,什麼意思呢?其實就是說 render()
不應該改變組件的狀態,每次調用都應該返回相同的結果,沒有副作用。同時也不應該直接與瀏覽器交互,應該要把交互的任務放在其他生命週期鉤子中。簡單來說可以把 render()
想成就只負責 return 一個渲染模板,其他什麼都盡量不要做。
注意,若
shouldComponentUpdate()
返回 false,則render()
不會被調用。下面會再講到shouldComponentUpdate()
。
componentDidMount()
componentDidMount()
componentDidMount()
會在渲染之後被立即調用。這個鉤子也可以說是 React 組件初始化的最後一個階段,如果需要從後端請求一些數據供組件渲染使用,使用 componentDidMount()
很適合。在這個鉤子中更改狀態都會引發視圖的重繪,用過 Vue 的話,可以把這個鉤子想成 Vue 中的 mounted()
鉤子。
更新狀態(Updating State)
shouldComponentUpdate()
shouldComponentUpdate(newProps, newState)
使用 shouldComponentUpdate()
可以做到讓 React 知道當前組件的狀態(state)或是屬性(props)改變是否不影響組件的輸出。默認行為是會在每次狀態改變進行重新渲染,而其實大部分情況下我們依賴默認行為就好。
當接收到新狀態或是新屬性時,shouldComponentUpdate()
會在渲染前被調用,默認返回 true,而返回 false 則可以阻止組件以及子組件因為狀態或是屬性的更新的重新渲染。
如果只定義了方法,但什麼都不返回,會報一個 warning:
shouldComponentUpdate(): Returned undefined instead of a boolean value.
注意,該方法不會在初始化渲染或是使用
forceUpdate()
時被調用,下面也會介紹到forceUpdate()
componentWillUpdate()
componentWillUpdate(newProps, newState)
當接收到新狀態或是新屬性時,componentWillUpdate()
會在渲染前被立即調用,也就是說,在更新發生之前,這個鉤子提供一個機會讓你對數據做一些操作,同樣,該方法不會在初始化渲染被調用。
注意,如果
shouldComponentUpdate()
返回 false 則該方法不會被調用
componentDidUpdate()
componentDidUpdate(newProps, newState)
當接收到新狀態或是新屬性時,componentDidUpdate()
會在渲染後被立即調用。同樣,該方法不會在初始化渲染被調用。
到這邊,應該大致上有一點概念了,來看看一個實際的代碼例子,會更清楚些。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv