又是一個(gè)老生常談的內(nèi)容,從ES6起已經(jīng)開(kāi)始使用class的方式去創(chuàng)建組件,這種創(chuàng)建方式上的變化也帶來(lái)了寫法和方法上的改變,做一個(gè)總結(jié)
1.創(chuàng)建組件的差異
ES6之前采用React.createClass()的方式去創(chuàng)建組件,所有跟生命周期相關(guān)的方法都以一個(gè)json的都放到對(duì)應(yīng)的小括號(hào)里,作為參數(shù),作為初始值
var Hello = React.createClass({
componentWillMount:function () {
console.log("我將要被加載出來(lái)");
},
render:function () {
console.log("渲染");
return <div>我被渲染出來(lái)了</div>;
},
componentDidMount:function () {
console.log("已經(jīng)加載完成");
}
})
ES6之后,JS也開(kāi)始有了class,所以寫法上就有了很大的變化
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
}
componentWillReceiveProps(nextProps) {
console.log('enter componentWillReceiveProps ' + this.props.caption)
}
componentWillMount() {
console.log('enter componentWillMount ' + this.props.caption);
}
}
首先在第一行引入react包文件,Component相當(dāng)于組件類的父類,只要?jiǎng)?chuàng)建組件就要繼承于這個(gè)父類,而且第一個(gè)React即使沒(méi)用上,也一定要寫,否則編譯不過(guò),第一個(gè)寫的是父類的構(gòu)造函數(shù),也就是說(shuō),因?yàn)閷懛ㄉ系牟煌?生命周期的函數(shù),也發(fā)生了變化
2.裝載過(guò)程 Mount
1.constructor
構(gòu)造函數(shù),當(dāng)然創(chuàng)建的時(shí)候也可以不寫,寫構(gòu)造函數(shù)兩種情況
1.綁定this,在ES6中每個(gè)成員在執(zhí)行時(shí),this并不是跟對(duì)象自動(dòng)綁定,所以為了方便使用,在構(gòu)造函數(shù)就將這個(gè)對(duì)象和this綁定好
2.初始化state,因?yàn)槭堑谝粋€(gè)執(zhí)行的生命周期函數(shù),所以在構(gòu)造函數(shù)初始化state最合適,也方便在其他過(guò)程使用state
而且在構(gòu)造函數(shù)的第一句,一定要寫super(props);不寫編譯不通過(guò).
2.getInitialState和getDefaultProps
getInitialState這個(gè)函數(shù)的作用會(huì)返回初始化組件的this.state,getDefaultProps的作用就是返回this.props,但是這兩個(gè)方法是配合React.createClass這種創(chuàng)建使用的,也就是說(shuō)ES6之后,這兩個(gè)方法就不能使用了,如果非常倔強(qiáng),就是要用,不影響編譯,但是在控制臺(tái)會(huì)有一個(gè)紅色warning

3.render
這個(gè)函數(shù)的地位毋庸置疑,非常重要,哪怕別的周期函數(shù)不寫,這個(gè)也一定要寫,因?yàn)楦割悓?duì)除render之外的函數(shù)都默認(rèn)實(shí)現(xiàn).render要對(duì)應(yīng)的是一個(gè)純函數(shù),它返回一個(gè)JSX描述的結(jié)構(gòu),最終通過(guò)React來(lái)完成渲染工作.
4.componentWillMount和componentDidMount
componentWillMount是優(yōu)先于render執(zhí)行的,在渲染之前之前執(zhí)行,如果想在這個(gè)函數(shù)寫點(diǎn)什么的話,那些代碼可以都移位到構(gòu)造函數(shù)中去寫,這個(gè)函數(shù)也可以認(rèn)為是相對(duì)componentDidMount存在的,用處也大,就是將要裝載這樣一個(gè)狀態(tài).
componentDidMount這個(gè)函數(shù)是在render之后調(diào)用,但是當(dāng)一個(gè)組件由多個(gè)子組件組成的時(shí)候,執(zhí)行順序會(huì)發(fā)生些許變化

三個(gè)組件的componentDidMount方法并沒(méi)有在各自組件render方法之后執(zhí)行,而是都最后一步統(tǒng)一執(zhí)行,這是因?yàn)閞ender只是返回一個(gè)結(jié)構(gòu)的描述,最終是靠React來(lái)完成渲染工作,所以React完成三個(gè)組件的轉(zhuǎn)載之后,才算完成整個(gè)裝載,才會(huì)調(diào)用componentDidMount這個(gè)函數(shù),所以都在最后一起調(diào)用.而且這個(gè)函數(shù)調(diào)用的時(shí)候能保證Dom樹(shù)已經(jīng)全部加載出來(lái)了,也可以在這個(gè)函數(shù)里使用Ajax進(jìn)行網(wǎng)絡(luò)請(qǐng)求,去做一些邏輯上的操作
整體下來(lái)裝載過(guò)程的生命周期函數(shù)執(zhí)行順序
constructor-> componentWillMount -> render -> componentDidMount
3.更新過(guò)程 Update
第一個(gè)大過(guò)程是組件被裝載到Dom上用戶對(duì)組件的第一印象的過(guò)程,但是在程序執(zhí)行的過(guò)程中,props和state可能隨時(shí)會(huì)發(fā)生變化,所以在過(guò)程中會(huì)一直處于一個(gè)更新的過(guò)程.這個(gè)過(guò)程有五個(gè)周期函數(shù)
1.componentWillReceiveProps(newProps)
這個(gè)函數(shù)的作用是當(dāng)父組件render被調(diào)用,對(duì)應(yīng)的子組件也會(huì)發(fā)生更新過(guò)程,不管這個(gè)過(guò)程中父組件傳給子組件的props有沒(méi)有發(fā)生變化,都會(huì)觸發(fā)子組件的componentWillReceiveProps,也就是這個(gè)方法實(shí)際上是在子組件被調(diào)用的,而且會(huì)把新的props傳給子組件,newProps就是對(duì)應(yīng)的參數(shù).這個(gè)方法是props更新會(huì)觸發(fā),this.state不會(huì)觸發(fā)調(diào)動(dòng)這個(gè)方法.最簡(jiǎn)單的方式就是父組件有一個(gè)按鈕,調(diào)用this.forceUpdate,強(qiáng)制讓React組件重新繪制,類似初始化
// 父組件
<Son caption="First" initValue={20} />
<button onClick={() => this.forceUpdate()}></button>
// 子組件
componentWillReceiveProps(newProps) {
console.log(newProps);
console.log('componentWillReceiveProps ' + this.props.initValue)
}
只要觸發(fā)重新繪制就能觸發(fā),方法不唯一
2.shouldComponentUpdate(nextProps, nextState)
render函數(shù)通過(guò)JSX告訴React需要渲染什么,shouldComponentUpdate的作用就是與之相反,告訴React哪些內(nèi)容不需要渲染.這個(gè)函數(shù)也和render一樣,需要一個(gè)返回值,但是這個(gè)返回值類型是bool,通過(guò)True和False告訴React在這次更新過(guò)程中,組件是夠需要更新,重新渲染.靈活使用這個(gè)函數(shù),可以大大的提高React的性能.
// 子組件
shouldComponentUpdate(newProps, newState) {
return (newProps.caption !== this.props.caption) ||
(newState.count !== this.state.count);
}
當(dāng)子組件要渲染之前,會(huì)觸發(fā)這個(gè)函數(shù),會(huì)把當(dāng)前新的props和新的state作為兩參數(shù)傳到函數(shù)里,當(dāng)然如果直接返回false,無(wú)論怎么樣都不會(huì)重新繪制了,所以可以根據(jù)值的變化進(jìn)行選擇性的繪制.而且在使用this.setState的時(shí)候,并不是第一時(shí)間更新組件組件上state相關(guān)的值,在執(zhí)行shouldComponentUpdate的時(shí)候this.state還是原來(lái)的值,并沒(méi)有發(fā)生變化,所以需要四個(gè)值都進(jìn)行比較.
3.componentWillUpdate和componentDidUpdate
當(dāng)上一步shouldComponentUpdate通過(guò)之后,會(huì)調(diào)用componentWillUpdate,render和componentDidUpdate,這兩個(gè)函數(shù)也會(huì)把render加在中間,作用跟componentWillMount和componentDidMount差不多,就不在贅述了
更新過(guò)程的生命周期執(zhí)行順序大致如下
componentWillReceiveProps -> shouldComponentUpdate -> componentWillUpdate -> render -> componentDidUpdate
4.卸載過(guò)程 Unmount
這個(gè)周期下只涉及到1個(gè)函數(shù)componentWillUnmount,當(dāng)React組件要從Dom樹(shù)上移除的時(shí)候會(huì)觸發(fā)這個(gè)函數(shù),做組件的收尾工作.
如果在開(kāi)始的時(shí)候使用componentDidMount創(chuàng)建了一些非React的方法創(chuàng)建的DOM元素,,就需要在卸載過(guò)程中,對(duì)這部分內(nèi)容進(jìn)行清除,防止造成不必要的內(nèi)存問(wèn)題
大將南征膽氣豪,腰橫秋水雁翎刀。
風(fēng)吹鼉鼓山河動(dòng),電閃旌旗日月高。
天上麒麟原有種,穴中螻蟻豈能逃。
太平待詔歸來(lái)日,朕與先生解戰(zhàn)袍