React組件的生命周期深入理解分析
組件從創(chuàng)建到銷毀的過程,被稱為組件的生命周期。
在生命周期的各個階段都有相對應(yīng)的鉤子函數(shù),會在特定的時機被調(diào)用,被稱為組件的生命周期鉤子。
生命周期回調(diào)函數(shù) = 生命周期鉤子函數(shù) = 生命周期函數(shù) = 生命周期鉤子
函數(shù)式組件沒有生命周期,因為生命周期函數(shù)是 React.Component 類的方法實現(xiàn)的,函數(shù)式組件沒有繼承 React.Component,所以也就沒有生命周期。
<-- 容器!--> <div id="test"></div> // 創(chuàng)建組件 class Life extends React.Component{ state = {opacity:1} // 調(diào)用時機:組件掛載完畢 componentDidMount(){ this.timer = setInterval(() => { let {opacity} = this.state opacity -= 0.1 if(opacity <= 0) opacity = 1 this.setState({opacity}) }, 200); } //調(diào)用時機:組件將要卸載 componentWillUnmount(){ clearInterval(this.timer) } handleUnmount = ()=>{ //卸載組件 ReactDOM.unmountComponentAtNode(document.getElementById('test')) } //調(diào)用時機:初始化渲染、狀態(tài)更新之后 render(){ return( <div> <h2 style={{opacity:this.state.opacity}}>我是一段透明度會變化的文字</h2> <button onClick={this.handleUnmount}>點擊卸載</button> </div> ) } } //渲染組件 ReactDOM.render(<Life/>,document.getElementById('test'))
生命周期鉤子(新)
新的生命周期鉤子增加了 getDerivedStateFromProps 和 getSnapshotBeforeUpdate。
constructor():constructor() 構(gòu)造函數(shù)在 React 組件掛載之前被調(diào)用。
如果不初始化 state 或不為事件處理函數(shù)綁定實例,則不需要寫 constructor()。
不能在 constructor() 構(gòu)造函數(shù)內(nèi)部調(diào)用 this.setState(), 因為此時第一次 render() 還未執(zhí)行,也就意味 DOM 節(jié)點還未掛載。
static getDerivedStateFromProps(nextProps, prevState):在每次調(diào)用 render() 方法之前都會被調(diào)用,在初始化和更新時都會被調(diào)用。
getDerivedStateFromProps() 第一個參數(shù)為即將更新的 props,第二個參數(shù)為上一個狀態(tài)的 state,可以比較 props 和 state 來加一些限制條件,防止無用的 state 更新。
getDerivedStateFromProps() 的返回值是必須的。返回一個對象來更新 state,如果不需要更新,返回 null 即可。 getDerivedStateFromProps() 適用于 state 的值在任何時候都取決于 props 的情況。 getDerivedStateFromProps() 是一個靜態(tài)函數(shù),是放在組件身上的,而不是放在組件實例身上,因此不能使用 this。
// 之前使用 componentWillReceiveProps componentWillReceiveProps(nextProps) { if (nextProps.location.search !== this.props.location.search) { this.init() } } // 現(xiàn)在使用 getDerivedStateFromProps:相當(dāng)于把 componentWillReceiveProps 拆分成 getDerivedStateFromProps 和 componentDidUpdate static getDerivedStateFromProps(nextProps, prevState) { const {search} = nextProps.location if (search !== prevState.search) { return { search, } } return null } componentDidUpdate(prevProps, prevState) { const {search} = this.state if (search !== prevState.search) { this.init() } }
render():render() 方法是類組件中唯一必須實現(xiàn)的方法,用于渲染 DOM,render() 方法必須返回 reactDOM。
在 render() 的 return 之前不能寫 setState,否則會觸發(fā)死循環(huán)導(dǎo)致內(nèi)存崩潰;return 體里面是可以寫的。
// Wrong render(){ this.setState({...}) return (...) } // Correct render(){ return ( <input onClick={()=>this.setState({...})} /> ) }
componentDidMount():在組件掛載后 (插入 DOM 樹后) 立即調(diào)用,此生命周期是發(fā)送網(wǎng)絡(luò)請求、開啟定時器、訂閱消息等的好時機,并且可以在此鉤子函數(shù)里直接調(diào)用 setState()。
shouldComponentUpdate(nextProps, nextState):在組件更新之前調(diào)用,可以控制組件是否進行更新, 返回 true 時組件更新, 返回 false 則不更新。不寫此生命周期鉤子時默認為 true。
shouldComponentUpdate() 第一個參數(shù)是即將更新的 props 值,第二個參數(shù)是即將更新后的 state 值,可以根據(jù)更新前后的 props 或 state 來比較加一些限制條件,決定是否更新,進行性能優(yōu)化。
不要在 shouldComponentUpdate 中調(diào)用 setState(),否則會導(dǎo)致無限循環(huán)調(diào)用更新、渲染,直至瀏覽器內(nèi)存崩潰。
getSnapshotBeforeUpdate(prevProps, prevState):在最新的渲染數(shù)據(jù)提交給 DOM 前會調(diào)用,也就是說,在 render 之后,在 componentDidUpdate 之前調(diào)用。使得組件可以在更新之前獲取快照值。不常用。
它可以使組件在 DOM 真正更新之前捕獲一些信息(例如滾動位置),此生命周期返回的任何值都會作為參數(shù)傳遞給 componentDidUpdate(),如不需要傳遞任何值,那么返回 null。返回值是必須的。
componentDidUpdate(prevProps, prevState, snapshot):componentDidUpdate() 會在更新后會被立即調(diào)用。首次渲染不會執(zhí)行。
包含三個參數(shù),第一個是上一次props值。 第二個是上一次state值,第三個是“snapshot” 參數(shù)傳遞。
可以進行前后 props 的比較進行條件語句的限制,來進行 setState() , 否則會導(dǎo)致死循環(huán)。
componentWillUnmount():componentWillUnmount() 在組件即將被卸載或銷毀時進行調(diào)用。此生命周期是清理定時器、取消訂閱等操作的好時機。
組件的掛載流程:
- constructor
- getDerivedStateFromProps
- render
- componentDidMount
setState 更新流程:
- getDerivedStateFromProps
- shouldComponentUpdate
- render
- getSnapshotBeforeUpdate
- componentDidUpdate
組件的卸載流程: componentWillUnmount
生命周期鉤子(舊)
React 從 v16.3 開始廢棄 componentWillMount、componentWillReceiveProps、componentWillUpdate 三個鉤子函數(shù)。在新版本中使用需要加上 UNSAFE_
前綴,否則會觸發(fā)控制臺的警告。
UNSAFE 不是指安全性,而是表示使用這些生命周期的代碼在 React 的未來版本中更有可能出現(xiàn) Bug,尤其是在啟用異步渲染之后。
組件的掛載流程:
- constructor
- componentWillMount
- render
- componentDidMount
setState 更新流程:
- shouldComponentUpdate
- componentWillUpdate(組件更新之前調(diào)用)
- render
- componentDidUpdate
forceUpdate 強制更新流程:
- componentWillUpdate(組件更新之前調(diào)用)
- render
- componentDidUpdate
父組件 render 之后子組件的更新流程:
- componentWillReceiveProps(子組件接收到新的 props 之前調(diào)用,第一次接收到 props 不會調(diào)用)
componentWillReceiveProps(nextProps) { // 可以和 this.props 中的數(shù)據(jù)進行對比,以決定是否要執(zhí)行某些方法 }
- shouldComponentUpdate
- componentWillUpdate(組件更新之前調(diào)用)
- render
- componentDidUpdate
組件的卸載流程:
componentWillUnmount
父子組件生命周期
當(dāng)子組件自身的 state 狀態(tài)改變,不會對父組件產(chǎn)生副作用的情況下,父組件不會進行更新,也就是不會觸發(fā)父組件的生命周期。
當(dāng)父組件狀態(tài)變化時(不會是否更改到傳給子組件的 props),會觸發(fā)自身和子組件對應(yīng)的生命周期。
render 以及 render 之前的生命周期,父組件先執(zhí)行;
render 之后的生命周期,子組件先執(zhí)行,并且是與父組件交替執(zhí)行。
父子組件初始化流程:
- 父組件constructor
- 父組件getDerivedStateFromProps
- 父組件render
- 子組件constructor
- 子組件getDerivedStateFromProps
- 子組件render
- 子組件componentDidMount
- 父組件componentDidMount
子組件修改自身的 state 狀態(tài)流程:
- 子組件getDerivedStateFromProps
- 子組件shouldComponentUpdate
- 子組件render
- 子組件getSnapshotBeforeUpdate
- 子組件componentDidUpdate
父組件修改 state 狀態(tài)流程:
- 父組件getDerivedStateFromProps
- 父組件shouldComponentUpdate
- 父組件render
- 子組件getDerivedStateFromProps
- 子組件shouldComponentUpdate
- 子組件render
- 子組件getSnapshotBeforeUpdate
- 父組件getSnapshotBeforeUpdate
- 子組件componentDidUpdate
- 父組件componentDidUpdate
父組件卸載子組件:
// 通過點擊父組件中的 [卸載 / 掛載子組件] 按鈕來卸載子組件 handelToggle = () => { this.setState({ isHidden: !this.state.isHidden }) } <button onClick={this.handelToggle}>掛載/卸載子組件</button> {this.state.isHidden ? '' : <Child />>}
- 父組件getDerivedStateFromProps
- 父組件shouldComponentUpdate
- 父組件render
- 父組件getSnapshotBeforeUpdate
- 子組件componentWillUnmount
- 組件componentDidUpdate
父組件重新掛載子組件:
再次點擊父組件中的 [卸載 / 掛載子組件] 按鈕來掛載子組件。
- 父組件getDerivedStateFromProps
- 父組件shouldComponentUpdate
- 父組件render
- 子組件constructor
- 子組件getDerivedStateFromProps
- 子組件render
- 父組件getSnapshotBeforeUpdate
- 子組件componentDidMount
- 父組件componentDidUpdate
到此這篇關(guān)于React組件的生命周期深入理解分析的文章就介紹到這了,更多相關(guān)React組件的生命周期內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React中memo useCallback useMemo方法作用及使用場景
這篇文章主要為大家介紹了React中三個hooks方法memo useCallback useMemo的作用及使用場景示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助2023-03-03react-router?v6實現(xiàn)動態(tài)路由實例
這篇文章主要為大家介紹了react-router?v6實現(xiàn)動態(tài)路由實例詳解,<BR>有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08淺析JS中什么是自定義react數(shù)據(jù)驗證組件
我們在做前端表單提交時,經(jīng)常會遇到要對表單中的數(shù)據(jù)進行校驗的問題。這篇文章主要介紹了js中什么是自定義react數(shù)據(jù)驗證組件,需要的朋友可以參考下2018-10-10深入學(xué)習(xí)TypeScript 、React、 Redux和Ant-Design的最佳實踐
這篇文章主要介紹了深入學(xué)習(xí)TypeScript 、React、 Redux和Ant-Design的最佳實踐,TypeScript 增加了代碼的可讀性和可維護性,擁有活躍的社區(qū),,需要的朋友可以參考下2019-06-06