react 生命周期
生命周期經(jīng)歷三個(gè)過程
- 裝載過程(mount), 也就是把組件第一次在DOM樹中渲染的過程
- 更新過程(updata), 當(dāng)組件被重新渲染的過程
- 卸載過程(Unmount), 組件充DOM中刪除的過程
三種不同的過程简烤,React庫(kù)會(huì)一次調(diào)用組件的一些成員函數(shù)截型,即生命周期鉤子
裝載過程中的生命周期鉤子
constructor
getinitialState
getDefaultProps
componentWillMount
render
componentDidMount
getinitialState、getDefaultProps
是React.createClass
創(chuàng)建組件時(shí)用到的生命周期函數(shù)阱当,在高版本的React中已經(jīng)放棄這種方法憨栽,所以這次就不進(jìn)行展示猾昆;
constructor
在面向?qū)ο缶幊讨斜鄹郏悾╟lass)是對(duì)象(object)的模板劳景,定義了同一組對(duì)象(又稱"實(shí)例")共有的屬性和方法。
Javascript語言不支持"類"柄沮,但是可以用一些變通的方法回梧,模擬出"類"。
constructor
ES6中每個(gè)類的構(gòu)造函數(shù)铡溪,并不是每個(gè)組件都需要定義自己的構(gòu)造函數(shù)漂辐,無狀態(tài)的React組件往往不需要定義構(gòu)造函數(shù)泪喊,一個(gè)React組件需要構(gòu)造函數(shù)棕硫,往往是為了下面的目的
- 初始化state,因?yàn)榻M件生命周期中任何函數(shù)都可以訪問state,那么整個(gè)生命周期中第一個(gè)被調(diào)用構(gòu)造函數(shù)自然是初始化state最理想的地方
- 綁定成員函數(shù)的this
在ES6語法下袒啼,類的每個(gè)成員函數(shù)在執(zhí)行時(shí)this應(yīng)不是和類實(shí)例自動(dòng)綁定的哈扮,而是在構(gòu)造函數(shù)中,this就是當(dāng)前組件實(shí)例蚓再,所以為了方便將來的調(diào)用滑肉,往往在構(gòu)造函數(shù)中將這個(gè)實(shí)例的特定函數(shù)綁定this為當(dāng)前實(shí)例
this.count = this.count.bind(this)
render
render 函數(shù)無疑是React
組件中最重要的函數(shù),一個(gè)React組件可以忽略其他所有函數(shù)都不實(shí)現(xiàn)摘仅,但是一定要實(shí)現(xiàn)render函數(shù)靶庙,因?yàn)镽eact組件的父類React.Component
類對(duì)除了render
之外的生命周期都有默認(rèn)實(shí)現(xiàn)
render 函數(shù)并不做實(shí)際的渲染動(dòng)作送滞,它返回一個(gè)JSX的描述的結(jié)構(gòu)鲸阻,最容由React來操作渲染過程
某些特殊組件的作用不是渲染潔面,或者蝗砾,組件在某些情況下沒有什么內(nèi)容取進(jìn)行更新矾端,那么讓render函數(shù)返回一個(gè)null或者false掏击,等于告訴React,這次組件不需要渲染任何DOM元素
注意: render 函數(shù)應(yīng)是一個(gè)純函數(shù),完全根據(jù)this.state
和 this.props
來決定返回的結(jié)果秩铆,而且不要產(chǎn)生任何副作用砚亭。在render函數(shù)中取調(diào)用this.setState
毫無疑問是錯(cuò)誤的,因?yàn)橐粋€(gè)純函數(shù)不應(yīng)該引起狀態(tài)的改變
componentWillMoun和componentDidMount
在裝載過程中,componentWillMount
會(huì)在調(diào)用render
函數(shù)前被調(diào)用捅膘,componentDidMount
則會(huì)在調(diào)用render
函數(shù)后被調(diào)用添祸,正好分別來做render前后必備的工作;
componentWillMount
放生在"將要裝載"的時(shí)候;這個(gè)時(shí)候沒有任何渲染出來的結(jié)果寻仗,即使調(diào)用this.setState
修改狀態(tài)也不會(huì)引發(fā)重新繪制膝捞,因?yàn)橐磺卸纪砹耍谶@個(gè)時(shí)候可以做的事情都可以放到constructor
中愧沟,可以認(rèn)為這個(gè)函數(shù)存在的主要目的是和componentDidMount
對(duì)稱蔬咬;
componentDidMount
調(diào)用在render
函數(shù)被調(diào)用完之后,componentDidMount
被調(diào)用的時(shí)候沐寺,render
函數(shù)返回的東西已經(jīng)引發(fā)了渲染林艘,組件已經(jīng)被"裝載"到DOM樹上;值得注意的時(shí)混坞,render
函數(shù)被調(diào)用后狐援,componentDidMount
函數(shù)并不是馬上被渲染;
代碼如下:
import React, { Component } from 'react';
import Counter from './Counter';
// app.js
class App extends React.Component {
render() {
console.log('enter ControlPanel render')
return (
<div className="App" >
<div style={{border: '1px solid', textAlign: 'center'}}>
<Counter caption="First" initValue={0}/>
<Counter caption="Second" initValue={10} />
<Counter caption="Third" initValue={20} />
</div>
</div>
)
}
}
// Counter.js
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = {
count: this.props.initValue,
name: this.props.caption
}
}
componentWillMount () {
console.log('render 運(yùn)行前': this.state.name)
}
componentDidMount () {
console.log('render 運(yùn)行后': this.state.count)
}
render () {
retrun (
<div>{this.state.name}: {this.state.count}<div>
)
}
}
結(jié)果:
可以清除的看到,componentDidMount是當(dāng)三個(gè)組件都調(diào)用完成后究孕,才一起被調(diào)用啥酱;
因?yàn)?code>render函數(shù)本身并不往DOM樹上渲染或者裝載內(nèi)容,它返回的是一個(gè)JSX表示的對(duì)象厨诸,然后由React庫(kù)根據(jù)返回對(duì)象決定如何渲染镶殷,而React庫(kù)把所有組件返回的結(jié)果綜合起來,才知道如何產(chǎn)生對(duì)應(yīng)的DOM修改微酬,所以React庫(kù)調(diào)用Counter三個(gè)組件的render函數(shù)后绘趋,才有可能完成狀態(tài),這個(gè)時(shí)候才會(huì)依次調(diào)用組件的
componentDIdMount
函數(shù)颗管;
更新過程
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
componentWillReceiveProps
只要父組件的render函數(shù)被調(diào)用陷遮,在render函數(shù)里面被渲染的子組件就會(huì)經(jīng)歷更新過程,不管父組件傳給子組件的props有沒有改變垦江,都會(huì)觸發(fā)子組件的componentWillReceiveProps函數(shù)帽馋。
// 代碼 接上部分代碼
// app.js
<button onClick={() => this.forceUpdate()}>aaaa</button>
// Counter.js
componentWillReceiveProps (nextProps) {
console.log('enter componentReceiveProps' + this.props.name)
}
shouldComponentUpdate(nextProps, nextState)
除了render函數(shù)外,shouldCompoentUpdate可能是整個(gè)組件生命周期中最重要的一個(gè)函數(shù)了比吭;
shouldCompoentUpdate
函數(shù)決定了一個(gè)組件什么時(shí)候不需要進(jìn)行渲染绽族;
shouldCompoentUpdate
和render
是React生命周期函數(shù)中唯二兩個(gè)要求有返回結(jié)果的函數(shù),render返回結(jié)果將用于構(gòu)造DOM對(duì)象梗逮,而shouldCompoentUpdate函數(shù)返回一個(gè)布爾值项秉,告訴React庫(kù)這個(gè)組件在本次更新中國(guó)呢是否繼續(xù);
在React庫(kù)首先調(diào)用shouldCompoentUpdate
函數(shù)慷彤,如果返回true則僅需更新娄蔼,調(diào)用render怖喻,如果返回false則停止更新過程,也不會(huì)引發(fā)后續(xù)渲染岁诉。
// 代碼接上面
// Counter.js
shouldComponentUpdate(nextProps, nextState) {
return (nextProps.count !== this.props.count) || (nextState.count !== this.state.count)
}
componentWillUpdate () {
console.log('componentWillUpdate')
}
componentDidUpdate () {
console.log('componentDidUpdate')
}
當(dāng)點(diǎn)擊aaaa進(jìn)行刷新時(shí)锚沸,不會(huì)調(diào)用shouldComponentUpdate
,同時(shí)也不會(huì)進(jìn)行componentWillUpdate
函數(shù)等的調(diào)用,當(dāng)進(jìn)行加減操作石涕癣,則觸發(fā)哗蜈;
componentWillUpdate和componentDidUpdate
componentWillUpdate
組件初始化時(shí)不調(diào)用,只有在組件將要更新時(shí)才調(diào)用坠韩,此時(shí)可以修改state
componentDidUpdate
組件初始化時(shí)不調(diào)用距潘,組件更新完成后調(diào)用,此時(shí)可以獲取dom節(jié)點(diǎn)只搁。
卸載過程
componentWillUnmount
防止內(nèi)存泄漏
用法官方實(shí)例