長(zhǎng)沙廣告公司排行榜上海優(yōu)化網(wǎng)站
概念
生命周期是一個(gè)組件叢創(chuàng)建,渲染,更新,卸載的過(guò)程,無(wú)論是vue還是react都具有這個(gè)設(shè)計(jì)概念,也是開(kāi)發(fā)者必須熟練運(yùn)用的,特別是業(yè)務(wù)開(kāi)發(fā),不同的生命周期做不同的事是很重要的.
....
多說(shuō)兩句心得,本人是先接觸vue的,無(wú)論是vue2還是vue3的生命周期,在理解和學(xué)習(xí)上都會(huì)比react更容易理解,我在學(xué)習(xí)react的時(shí)候,也經(jīng)常會(huì)想著這個(gè)api如果在vue里面會(huì)和哪個(gè)api功能相同.
其實(shí)有些本末倒置了,先有react才有的vue,vue是作者做了更多的操作,讓你用到更舒適的api,還是那個(gè)經(jīng)典形容,react是手動(dòng)打,vue是自動(dòng)擋.
廢話不多說(shuō),開(kāi)始說(shuō)react的生命周期
...
如果想直接死記硬背八股文,直接拉到底看總結(jié)就可以了
類式組件
在hooks出來(lái)之前,寫(xiě)react基本都是用類式組件
兩個(gè)原因,一是對(duì)this這個(gè)東西有特別的喜愛(ài)(vue后遺癥),二是類式組件可以使用生命周期和state,適合開(kāi)發(fā)業(yè)務(wù)組件.
測(cè)試各個(gè)鉤子函數(shù)的demo
import React, { Component} from 'react'
export default class index extends Component {constructor(){super()console.log(this,'constructor---構(gòu)造器')}state = {num:1}add = ()=>{let newNum = this.state.num +1this.setState({num:newNum})}//生命周期鉤子(舊的)
// componentWillMount =()=>{
// console.log('componentWillMount---組件將要加載')
// }// componentWillUpdate = ()=>{
// console.log('componentWillUpdate','組件將要更新')
// }//生命周期鉤子(新的)
static getDerivedStateFromProps = ()=>{console.log(this,'getDerivedStateFromProps---初始化一些基礎(chǔ)狀態(tài)')return null
}getSnapshotBeforeUpdate = ()=>{console.log(this,'getSnapshotBeforeUpdate---更新之前的快照')return '舊的值'
}//新舊都具備的shouldComponentUpdate = ()=>{console.log(this,'shouldComponentUpdate','組件需要更新')return true}componentDidUpdate = ()=>{console.log(this,'componentDidUpdate','組件更新完畢')}componentDidMount = ()=>{console.log(this,'componentDidMount---組件加載完成')}updateCallBack = ()=>{this.forceUpdate()}render() {console.log(this,'render---渲染函數(shù)')return (<div id='index'><h3>生命周期模塊</h3> <button onClick={this.add}>修改一下數(shù)值</button><p>{this.state.num}</p><button onClick={this.updateCallBack}>手動(dòng)更新</button><br /></div>)}componentWillUnmount = ()=>{console.log(this,'componentWillUnmount---組件將要卸載')}
}
場(chǎng)景:
1.頁(yè)面初次加載
constructor >?getDerivedStateFromProps > render >?componentDidMount
2.點(diǎn)擊修改一下數(shù)值按鈕
getDerivedStateFromProps > shouldComponentUpdate > render > getSnapshotBeforeUpdate >
componentDidUpdate
?3.手動(dòng)更新(forceUpdate函數(shù))
getDerivedStateFromProps > render >?getSnapshotBeforeUpdate > componentDidUpdate
?4.卸載當(dāng)前組件
componentWillUnmount
生命周期經(jīng)典圖
解讀一下:
好吧,其實(shí)沒(méi)有什么太多好解讀的,本人的react內(nèi)力沒(méi)有那么深厚,這張圖就是剛才我們實(shí)驗(yàn)的結(jié)果
初始化,自動(dòng)更新,手動(dòng)更新,卸載
你只要把這個(gè)demo自己寫(xiě)一下,就瞬間知道這個(gè)圖是干啥的了,除了很長(zhǎng)的單詞比較難寫(xiě),其余都好說(shuō).
你以為這樣就完了嗎,不不不,沒(méi)有沒(méi)有沒(méi)有.這里還有兩個(gè)需要專門說(shuō)的
兩個(gè)疑問(wèn)
1.生命周期連續(xù)調(diào)用了兩次的問(wèn)題
造成這個(gè)原因是因?yàn)槟愕母M件使用了嚴(yán)格模式 React.StrictMode
ReactDOM.createRoot(document.getElementById('root')).render(<Provider store={store}>{/* <React.StrictMode> 把它注釋掉就可以了*/} <App />{/* </React.StrictMode> */}</Provider>
)
2.父子組件生命周期順序(測(cè)試demo)
初始化
父costructor > 父 getDerviedStateFromProps > 父render >子costructor >子getDerviedStateFromProps > 子render > 子componentDidMount >父componentDidMount
?父組件修改值觸發(fā)更新
父 getDerivedStateFromProps > 父 shouldComponentUpdate > 父 render > 子 getDrivedStateFromprops > 子shouldComponentUpdate > 子 render > 子 getSnaphotBeforeUpdate > 父getSnapshotBeforeUpdate > 子 componentDidUpdate> 父 componentDidUpdate
父組件手動(dòng)更新
父 getDerivedStateFromProps > 父render > 子 getDerivedStateFromProps > 子 shouldComponentUpdate > 子render > 子getSnapshotBeforeUpdate > 父getSnapshotBeforeUpdate > 子componentDidUpdate > 父componentDidUpdate
?組件卸載
父componentWillUnmount > 子componentWillUnmount
函數(shù)組件
函數(shù)組件實(shí)現(xiàn)生命周期是需要借助一個(gè)api的,這個(gè)api叫做useEffect.
demo
import React,{useState,useEffect} from 'react'
import {Button} from 'antd'
export default function index(props) {const [num1,changeNum1] = useState(0)const [num2,changeNum2] = useState(10)//單個(gè)-----------------------------------------------------//首次加載,修改num1,修改num2,卸載當(dāng)前組件沒(méi)有useEffect(()=>{console.log('只傳一個(gè)函數(shù)')})//首次加載,num1沒(méi)有,num2沒(méi)有,卸載當(dāng)前組件沒(méi)有useEffect(()=>{console.log('參數(shù)二傳一個(gè)空數(shù)組')},[])//首次加載,修改num1,num2沒(méi)有,卸載當(dāng)前組件沒(méi)有useEffect(()=>{console.log('傳參數(shù)num1')},[num1])//首次加載,num1沒(méi)有,修改num2,卸載當(dāng)前組件沒(méi)有useEffect(()=>{console.log('傳參數(shù)num2')},[num2])//首次加載,修改num1,修改num2,卸載當(dāng)前組件沒(méi)有useEffect(()=>{console.log('都傳')},[num1,num2])//首次沒(méi)有,修改num1,修改num2,卸載組件調(diào)用useEffect(()=>{return ()=>{console.log('return方法')}})// 總結(jié):// 1.參數(shù)1:函數(shù): 初始化和每次修改參數(shù)都會(huì)觸發(fā)這個(gè)函數(shù)// 2.參樹(shù)2:空數(shù)組: 只有首次加載會(huì)觸發(fā)// 3.參數(shù)2:某條數(shù)據(jù): 首次加載和修改該數(shù)據(jù)都會(huì)觸發(fā)// 4.參數(shù)2:多條數(shù)據(jù): 首次加載和修改數(shù)組內(nèi)任意一條數(shù)據(jù)都會(huì)觸發(fā)// 5.參數(shù)1:函數(shù)返回一個(gè)函數(shù): 首次不急在,但是修改任意數(shù)值和卸載組件時(shí)都會(huì)調(diào)用return (<div><p>數(shù)值1:{num1}<Button onClick={()=>changeNum1(num1+1)}>修改數(shù)值1</Button></p><p>數(shù)值2:{num2}<Button onClick={()=>changeNum2(num2-1)}>修改數(shù)值2</Button></p></div>)
}
?初始化
?修改值1
組件卸載
實(shí)現(xiàn)初始化,更新,單獨(dú)的數(shù)據(jù)更新,卸載
import React,{useState,useEffect} from 'react'
import {Button} from 'antd'
export default function index(props) {const [num1,changeNum1] = useState(0)const [num2,changeNum2] = useState(10)// 組合------------------------------------------------------// 場(chǎng)景1: 初始化加載useEffect(()=>{console.log('初始化加載')console.log(num1,'???',props)},[])//場(chǎng)景2: 任意數(shù)據(jù)更新,但是初始化不加載useEffect(()=>{return ()=>{console.log('數(shù)據(jù)發(fā)生修改了')}})//場(chǎng)景3: 只有卸載時(shí)加載useEffect(()=>{return ()=>{console.log('卸載才會(huì)調(diào)用')}},[])//場(chǎng)景4: 某一數(shù)據(jù)發(fā)生改變,單獨(dú)觸發(fā)useEffect(()=>{return ()=>{console.log('只有修改num1才會(huì)調(diào)用')}},[num1])return (<div><p>數(shù)值1:{num1}<Button onClick={()=>changeNum1(num1+1)}>修改數(shù)值1</Button></p><p>數(shù)值2:{num2}<Button onClick={()=>changeNum2(num2-1)}>修改數(shù)值2</Button></p></div>)
}
總結(jié)
類式組件
各階段鉤子調(diào)用順序
初始化 | constructor > getDerivedStateFromProps > render >?componentDidMount |
自動(dòng)更新 | getDerivedStateFromProps > shouldComponentUpdate > render > getSnapshotBeforeUpdate > componentDidUpdate? |
手動(dòng)更新 | getDerivedStateFromProps > render >?getSnapshotBeforeUpdate > componentDidUpdate |
卸載 | componentWillUnmount |
父子組件生命周期
初始化 | 父costructor > 父 getDerviedStateFromProps > 父render >子costructor >子getDerviedStateFromProps > 子render > 子componentDidMount >父componentDidMount |
父組件自動(dòng)更新 | 父 getDerivedStateFromProps > 父 shouldComponentUpdate > 父 render > 子 getDrivedStateFromprops > 子shouldComponentUpdate > 子 render > 子 getSnaphotBeforeUpdate > 父getSnapshotBeforeUpdate > 子 componentDidUpdate> 父 componentDidUpdate |
父組件手動(dòng)更新 | 父 getDerivedStateFromProps > 父render > 子 getDerivedStateFromProps > 子 shouldComponentUpdate > 子render > 子getSnapshotBeforeUpdate > 父getSnapshotBeforeUpdate > 子componentDidUpdate > 父componentDidUpdate |
卸載 | 父componentWillUnmount > 子componentWillUnmount |
鉤子函數(shù)連續(xù)調(diào)用兩次的問(wèn)題解決
干掉根組件的?React.StrictMode
函數(shù)組件
只在初始化加載調(diào)用 | ? ? useEffect(()=>{ ? ? ? ? console.log('初始化加載') ? ? },[]) |
初始化不調(diào)用但是更新組件會(huì)調(diào)用 | ? ? useEffect(()=>{ ? ? ? ? return ()=>{ ? ? ? ? ? ? console.log('數(shù)據(jù)發(fā)生修改了') ? ? ? ? } ? ? }) |
單獨(dú)的數(shù)據(jù)發(fā)生變化進(jìn)行調(diào)用 | ? ? useEffect(()=>{ ? ? ? ? return ()=>{ ? ? ? ? ? ? console.log('只有修改num1才會(huì)調(diào)用') ? ? ? ? } ? ? },[num1]) |
只在組件卸載時(shí)調(diào)用 | ? ? useEffect(()=>{ ? ? ? ? return ()=>{ ? ? ? ? ? ? console.log('卸載才會(huì)調(diào)用') ? ? ? ? } ? ? },[]) |
尾聲
我的這篇博客沒(méi)有專門講這些api在調(diào)用時(shí)都發(fā)生了啥,主要是讓讀者了解react生命周期的api調(diào)用時(shí)機(jī),屬于業(yè)務(wù)開(kāi)發(fā)中實(shí)用知識(shí)點(diǎn),感覺(jué)還行的看客老爺們給個(gè)贊吧!