組件繼承了react Component等相關(guān)基類,也就是繼承了react的基類小压,才有render() , 生命周期等方法可以使用泥从,這也說(shuō)明了函數(shù)組件(無(wú)狀態(tài)組件)不能使用這些方法的原因。
組件初始化階段
類的構(gòu)造方法(constructor())用來(lái)做組件的初始化工作
super(props)用來(lái)調(diào)用基類的構(gòu)造方法,也將父組件的props注入給子組件缰儿,供子組件讀取
組件中props只讀不可變锦秒,state可變露泊。
import React, { Component } from 'react';
class Test extends Component {
constructor(props) {
super(props);
}
}
constructor(props) {
super(props);
this.comboxHtmlOut = this.props.comboxHtmlOut;
this.pathQuery=this.props.pathQuery
}
state = {
employeeData: {},
submitLoading: false,
selectData:[]
};
constructor()接收兩個(gè)參數(shù)props,context
可以獲取到父組件傳下來(lái)的props,context,如果想在constructor構(gòu)造函數(shù)內(nèi)部 (注意是內(nèi)部哦,在組件其他地方是可以直接接收的)使用props或context,則需要傳入旅择,并傳入super對(duì)象惭笑。
constructor(props,context) {
super(props,context)
console.log(this.props,this.context) // 在內(nèi)部可以使用props和context
}
注意:只要組件存在constructor,就必須要寫(xiě)super,否則this指向就會(huì)錯(cuò)誤
constructor() {
console.log(this) // 報(bào)錯(cuò),this指向錯(cuò)誤
}
組件掛載階段
此階段分為componentWillMount , render , componentDidMOunt 三個(gè)時(shí)期
componentWillMount
在組件掛載到DOM前調(diào)用生真,且只會(huì)被調(diào)用一次沉噩,在這邊調(diào)用this.setState不會(huì)引起組件重新渲染,也可以把寫(xiě)在這邊的內(nèi)容提前到constructor()中柱蟀。
1)組件剛經(jīng)過(guò)constructor初始完數(shù)據(jù)
2)組件未進(jìn)入render,未完成渲染
注意:ajax請(qǐng)求不推薦寫(xiě)在這里
原因:
1)雖然有些情況下并不會(huì)出錯(cuò)川蒙,但是如果ajax請(qǐng)求過(guò)來(lái)的數(shù)據(jù)是空,那么會(huì)影響頁(yè)面的渲染长已,可能看到的就是空白畜眨。(個(gè)人覺(jué)得只要做好相應(yīng)的異常處理操作即可避免該問(wèn)題)
2)不利于服務(wù)端渲染,在同構(gòu)的情況下术瓮,生命周期會(huì)到componentwillmount康聂,這樣使用ajax就會(huì)出錯(cuò)
render
根據(jù)組件的props和state(只要兩者重傳遞和重賦值,無(wú)論值是否有變化胞四,都可以引起組件重新render),renter出一個(gè)react元素,不負(fù)責(zé)組件實(shí)際渲染工作早抠,之后由React自身根據(jù)此元素去渲染出頁(yè)面DOM。render是純函數(shù)(Pure function:函數(shù)的返回結(jié)果只依賴于它的參數(shù)撬讽;函數(shù)執(zhí)行過(guò)程里面沒(méi)有副作用)蕊连,不能在里面執(zhí)行this.setState,會(huì)有改變組件狀態(tài)的副作用游昼。
render函數(shù)會(huì)插入jsx生成的dom結(jié)構(gòu)甘苍,react會(huì)生成一份虛擬dom樹(shù),在每一次組件更新時(shí)烘豌,在此react會(huì)通過(guò)其diff算法比較更新前后的新舊DOM樹(shù)载庭,比較以后,找到最小的有差異的DOM節(jié)點(diǎn),并重新渲染
react16中 render函數(shù)允許返回一個(gè)數(shù)組囚聚,單個(gè)字符串等靖榕,不在只限制為一個(gè)頂級(jí)DOM節(jié)點(diǎn),可以減少很多不必要的div(當(dāng)然注意升級(jí)你的react版本顽铸,將現(xiàn)有項(xiàng)目升到react16并不會(huì)出現(xiàn)什么bug茁计,唯一注意的是proTypes類型檢測(cè)換了名字~)
eg:
render () {
return " "
}
render () {
return [
<div></div>
<div></div>
]
}
componentDidMount
組件掛載到DOM后調(diào)用,且只會(huì)被調(diào)用一次
組件第一次渲染完成谓松,此時(shí)dom節(jié)點(diǎn)已經(jīng)生成星压,可以在這里調(diào)用ajax請(qǐng)求,返回?cái)?shù)據(jù)setState后組件會(huì)重新渲染
組件更新階段
setState引起的state更新或父組件重新render引起的props更新鬼譬,更新后的state和props相對(duì)之前無(wú)論是否有變化娜膘,都將引起子組件的重新render。
組件更新兩類(三種)情況:
1.父組件重新render
1)直接使用优质,每當(dāng)父組件重新render導(dǎo)致的重傳props,子組件將直接跟著重新渲染竣贪,無(wú)論props是否有變化」Γ可通過(guò)shouldComponentUpdata方法優(yōu)化演怎。
class Child extends Component {
shouldComponentUpdate(nextProps){ // 應(yīng)該使用這個(gè)方法,否則無(wú)論props是否有變化都將會(huì)導(dǎo)致組件跟著重新渲染
if(nextProps.someThings === this.props.someThings){
return false
}
}
render() {
return <div>{this.props.someThings}</div>
}
}
2)在componentWillReceiveProps方法中牺六,將props轉(zhuǎn)換成自己的state
class Child extends Component {
constructor(props) {
super(props);
this.state = {
someThings: props.someThings
};
}
componentWillReceiveProps(nextProps) { // 父組件重傳props時(shí)就會(huì)調(diào)用這個(gè)方法
this.setState({someThings: nextProps.someThings});
}
render() {
return <div>{this.state.someThings}</div>
}
}
在該函數(shù)(componentWillReceiveProps)中調(diào)用 this.setState() 將不會(huì)引起第二次渲染
是因?yàn)閏omponentWillReceiveProps中判斷props是否變化了颤枪,若變化了汗捡,this.setState將引起state變化淑际,從而引起render,此時(shí)就沒(méi)必要再做第二次因重傳props引起的render了扇住,不然重復(fù)做一樣的渲染了春缕。
2.組件本身調(diào)用setState,無(wú)論state有沒(méi)有變化艘蹋〕簦可通過(guò)shouldComponentUpdate方法優(yōu)化。
class Child extends Component {
constructor(props) {
super(props);
this.state = {
someThings:1
}
}
shouldComponentUpdate(nextStates){ // 應(yīng)該使用這個(gè)方法女阀,否則無(wú)論state是否有變化都將會(huì)導(dǎo)致組件重新渲染
if(nextStates.someThings === this.state.someThings){
return false
}
}
handleClick = () => { // 雖然調(diào)用了setState 宅荤,但state并無(wú)變化
const preSomeThings = this.state.someThings
this.setState({
someThings: preSomeThings
})
}
render() {
return <div onClick = {this.handleClick}>{this.state.someThings}</div>
}
}
此階段分為componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,render,componentDidUpdate
componentWillReceiveProps(nextProps)
此方法只調(diào)用于props引起的組件更新過(guò)程中,參數(shù)nextProps是父組件傳給當(dāng)前組件的新props浸策。但父組件render方法的調(diào)用不能保證重傳給當(dāng)前組件的props是有變化的冯键,所以在此方法中根據(jù)nextProps和this.props來(lái)查明重傳的props是否改變,以及如果改變了要執(zhí)行啥庸汗,比如根據(jù)新的props調(diào)用this.setState出發(fā)當(dāng)前組件的重新render
componentWillReceiveProps在接受父組件改變后的props需要重新渲染組件時(shí)用到的比較多
它接受一個(gè)參數(shù)nextProps
通過(guò)對(duì)比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的第二個(gè)參數(shù)(回調(diào))可以打印出新的state
})
}
<BusinessRight
filterId={this.state.rightFilterId}
/>
******************************************************
componentWillReceiveProps(nextProps) {
if (nextProps.filterId !== this.props.filterId) {
let filterParame={
businessModelId:nextProps.filterId
}
this.setState({filterParame})
this.reloadList(apiUrl.list,nextProps,undefined,filterParame)
}
}
shouldComponentUpdate(nextProps, nextState)
唯一用于控制組件重新渲染的生命周期改化,由于在react中掩蛤,setState以后,state發(fā)生變化陈肛,組件會(huì)進(jìn)入重新渲染的流程揍鸟,(暫時(shí)這么理解,其實(shí)setState以后有些情況并不會(huì)重新渲染燥爷,比如數(shù)組引用不變)在這里return false可以阻止組件的更新
因?yàn)閞eact父組件的重新渲染會(huì)導(dǎo)致其所有子組件的重新渲染蜈亩,這個(gè)時(shí)候其實(shí)我們是不需要所有子組件都跟著重新渲染的,因此需要在子組件的該生命周期中做判斷
此方法通過(guò)比較nextProps前翎,nextState及當(dāng)前組件的this.props稚配,this.state,返回true時(shí)當(dāng)前組件將繼續(xù)執(zhí)行更新過(guò)程港华,返回false則當(dāng)前組件更新停止道川,以此可用來(lái)減少組件的不必要渲染,優(yōu)化組件性能
對(duì)于react初學(xué)者立宜,可能涉及這個(gè)生命周期的機(jī)會(huì)比較少冒萄,但是如果你的項(xiàng)目開(kāi)始注重性能優(yōu)化,隨著你對(duì)react的喜愛(ài)和深入橙数,你就會(huì)用到這個(gè)生命周期
componentWillUpdate(nextProps, nextState)
此方法在調(diào)用render方法前執(zhí)行尊流,在這邊可執(zhí)行一些組件更新發(fā)生前的工作,一般較少用灯帮。
shouldComponentUpdate返回true以后崖技,組件進(jìn)入重新渲染的流程,進(jìn)入componentWillUpdate,這里同樣可以拿到nextProps和nextState
render
render方法在上文講過(guò)钟哥,這邊只是重新調(diào)用迎献。
componentDidUpdate(prevProps, prevState)
此方法在組件更新后被調(diào)用,可以操作組件更新的DOM腻贰,prevProps和prevState這兩個(gè)參數(shù)指的是組件更新前的props和state
組件更新完畢后吁恍,react只會(huì)在第一次初始化成功會(huì)進(jìn)入componentDidmount,之后每次重新渲染后都會(huì)進(jìn)入這個(gè)生命周期,這里可以拿到prevProps和prevState播演,即更新前的props和state冀瓦。
卸載階段
此階段只有一個(gè)生命周期方法:componentWillUnmount
componentWillUnmount
此方法在組件被卸載前調(diào)用,可以在這里執(zhí)行一些清理工作写烤,比如清楚組件中使用的定時(shí)器翼闽,清楚componentDidMount中手動(dòng)創(chuàng)建的DOM元素等,以避免引起內(nèi)存泄漏顶霞。
eg:
componentDidMount() {
this.isMount === true
axios.post().then((res) => {
this.isMount && this.setState({ // 增加條件ismount為true時(shí)
aaa:res
})
})
}
componentWillUnmount() {
this.isMount === false
}