寫react也快半年了布隔,講一下自己對于生命周期的理解及各個生命周期的作用
首先,看一下一個組件的構(gòu)造
import React,{ Component } from 'react';
class Demo extends Component {
constructor(props,context) {
super(props,context)
this.state = {
//定義state
}
}
componentWillMount () {
}
componentDidMount () {
}
componentWillReceiveProps (nextProps) {
}
shouldComponentUpdate (nextProps,nextState) {
}
componentWillUpdate (nextProps,nextState) {
}
componentDidUpdate (prevProps,prevState) {
}
render () {
return (
<div></div>
)
}
componentWillUnmount () {
}
}
export default Demo;
當(dāng)然前段時間react16發(fā)布還新加了處理錯誤信息的生命周期 componentDidCatch(打個標記 還未使用過戴差,下次深入研究)
下面我從constructor構(gòu)造函數(shù)開始,從參數(shù)铛嘱,作用暖释,用法各方面總結(jié)
1、constructor
constructor參數(shù)接受兩個參數(shù)props,context
可以獲取到父組件傳下來的的props,context,如果你想在constructor構(gòu)造函數(shù)內(nèi)部(注意是內(nèi)部哦墨吓,在組件其他地方是可以直接接收的)使用props或context,則需要傳入球匕,并傳入super對象。
constructor(props,context) {
super(props,context)
console.log(this.props,this.context) // 在內(nèi)部可以使用props和context
}
當(dāng)然如果你只需要在構(gòu)造函數(shù)內(nèi)使用props或者context帖烘,那么只傳入一個參數(shù)即可亮曹,如果都不可以,就都不傳。
關(guān)于ES6的class constructor和super
只要組件存在constructor,就必要要寫super,否則this指向會錯誤
constructor() {
console.log(this) // 報錯乾忱,this指向錯誤
}
2、componentWillMount 組件將要掛載
1历极、組件剛經(jīng)歷constructor,初始完數(shù)據(jù)
2窄瘟、組件還未進入render,組件還未渲染完成趟卸,dom還未渲染
componentWillMount 一般用的比較少蹄葱,更多的是用在服務(wù)端渲染,(我還未使用過react服務(wù)端渲染哈锄列,所以也寫不了很多)
但是這里有一個問題
ajax請求能寫在willmount里嗎图云?
:答案是不推薦,別這么寫
1.雖然有些情況下并不會出錯邻邮,但是如果ajax請求過來的數(shù)據(jù)是空竣况,那么會影響頁面的渲染,可能看到的就是空白筒严。
2.不利于服務(wù)端渲染丹泉,在同構(gòu)的情況下,生命周期會到componentwillmount鸭蛙,這樣使用ajax就會出錯
3摹恨、componentDidMount 組件渲染完成
組件第一次渲染完成,此時dom節(jié)點已經(jīng)生成娶视,可以在這里調(diào)用ajax請求晒哄,返回數(shù)據(jù)setState后組件會重新渲染
4.componentWillReceiveProps (nextProps)
componentWillReceiveProps在接受父組件改變后的props需要重新渲染組件時用到的比較多
它接受一個參數(shù)
1.nextProps
通過對比nextProps和this.props,將nextProps setState為當(dāng)前組件的state肪获,從而重新渲染組件
componentWillReceiveProps (nextProps) {
nextProps.openNotice !== this.props.openNotice && this.setState({
openNotice:nextProps.openNotice
}寝凌,() => {
console.log(this.state.openNotice:nextProps) //將state更新為nextProps,在setState的第二個參數(shù)(回調(diào))可以打印出新的state
})
}
關(guān)于setState的用法及深入了解 后面會專門整理一篇文章
5.shouldComponentUpdate(nextProps,nextState)
唯一用于控制組件重新渲染的生命周期,由于在react中贪磺,setState以后硫兰,state發(fā)生變化,組件會進入重新渲染的流程寒锚,(暫時這么理解劫映,其實setState以后有些情況并不會重新渲染,比如數(shù)組引用不變)在這里return false可以阻止組件的更新
因為react父組件的重新渲染會導(dǎo)致其所有子組件的重新渲染刹前,這個時候其實我們是不需要所有子組件都跟著重新渲染的泳赋,因此需要在子組件的該生命周期中做判斷
對于react初學(xué)者,可能涉及這個生命周期的機會比較少喇喉,但是如果你的項目開始注重性能優(yōu)化祖今,隨著你對react的喜愛和深入,你就會用到這個生命周期
6.componentWillUpdate (nextProps,nextState)
shouldComponentUpdate返回true以后,組件進入重新渲染的流程千诬,進入componentWillUpdate,這里同樣可以拿到nextProps和nextState
7.render函數(shù)
render函數(shù)會插入jsx生成的dom結(jié)構(gòu)耍目,react會生成一份虛擬dom樹,在每一次組件更新時徐绑,在此react會通過其diff算法比較更新前后的新舊DOM樹邪驮,比較以后,找到最小的有差異的DOM節(jié)點傲茄,并重新渲染
react16中 render函數(shù)允許返回一個數(shù)組毅访,單個字符串等,不在只限制為一個頂級DOM節(jié)點盘榨,可以減少很多不必要的div(當(dāng)然注意升級你的react版本喻粹,將現(xiàn)有項目升到react16并不會出現(xiàn)什么bug,唯一注意的是proTypes類型檢測換了名字~)
意思你現(xiàn)在可以這樣:
render () {
return " "
}
或者這樣:
render () {
return [
<div></div>
<div></div>
]
}
8草巡、componentDidUpdate(prevProps,prevState)
組件更新完畢后守呜,react只會在第一次初始化成功會進入componentDidmount,之后每次重新渲染后都會進入這個生命周期,這里可以拿到prevProps和prevState山憨,即更新前的props和state弛饭。
如果你理解了組件一次重新渲染的過程,那么你應(yīng)該理解下面5處打印出來的state應(yīng)該是相同的萍歉。(關(guān)于setState異步是同步的理解侣颂,后面也會整理一篇文章~)
componentWillReceiveProps (nextProps,nextState) {
this.setState({
fengfeng:nextProps.fengfeng
},()=>{
console.log(this.state.fengfeng) //1
})
}
shouldComponentUpdate (nextProps,nextState) {
console.log(nextState.fengfeng) //2
}
componentWillUpdate (nextProps,nextState) {
console.log(nextState.fengfeng) //3
}
componentDidUpdate (prevProps,prevState) {
console.log(this.state.fengfeng) //5
}
render () {
console.log(this.state.fengfeng) //4
return (
<div></div>
)
}
9、componentWillUnmount ()
componentWillUnmount也是會經(jīng)常用到的一個生命周期枪孩,初學(xué)者可能用到的比較少憔晒,但是用好這個確實很重要的哦
1.clear你在組建中所有的setTimeout,setInterval
2.移除所有組建中的監(jiān)聽 removeEventListener
3.也許你會經(jīng)常遇到這個warning:
Can only update a mounted or mounting component. This usually means you called setState() on an
unmounted component. This is a no-op. Please check the code for the undefined component.
是因為你在組建中的ajax請求返回中setState,而你組件銷毀的時候,請求還未完成蔑舞,因此會報warning
解決辦法為
componentDidMount() {
this.isMount === true
axios.post().then((res) => {
this.isMount && this.setState({ // 增加條件ismount為true時
aaa:res
})
})
}
componentWillUnmount() {
this.isMount === false
}
拓展:
1.react生命周期父子組件渲染順序
父子組件拒担, componentWillMount生命周期是先進入父組件還是子組件?
componentDidMount呢攻询?
答案參考我的另一篇文章http://www.reibang.com/p/ee122bb5b14b