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