一. React的生命周期
這里render渲染函數(shù)會執(zhí)行兩次,第一次是當組件初始化完成的時候,第二次是當組件完成從數(shù)據(jù)的修改的時候再執(zhí)行一次
1.創(chuàng)建和初始化到的生命周期:
(1) getDefaultProps(15.6版本的):初始化props值
? ? (2)componentWillReceiveProps(廢棄): 這是監(jiān)聽props值變化的生命周期
? ? (3) getInitialState(15.6版本):初始化state值
2. 掛載階段:
? ? (1)componentWillMount: 掛載之前,在這里執(zhí)行的東西是在render(讓虛擬DOM轉(zhuǎn)換為真實DOM)函數(shù)的前面轨奄,這個生命周期在17版本之后就會被廢棄汇跨,現(xiàn)在它是一個不安全的生命周期
? ? ? ? ? ? ? (a)可以獲取this以及state里面的數(shù)據(jù)呛占,不可以獲取DOM元素
? ? ? ? ? ? ? 在這個生命周期里面修改數(shù)據(jù)可以直接引起頁面的改變,這是因為這個生命周期的執(zhí)行是在render渲染函數(shù)之前執(zhí)行的暴区,如果在這個生命周期里面修改數(shù)據(jù)闯团,也就是修改數(shù)據(jù)的時候render還沒有渲染頁面,當執(zhí)行完這個生命周期之后就去執(zhí)行render函數(shù)仙粱,這個時候就會根據(jù)這個生命周期修改以后的數(shù)據(jù)離開渲染頁面
? ? ? ? ? ? ? (b)但是不會觸發(fā)其他運行中的生命周期
? ? ? ? ? ? ? (c)這個生命周期不常用房交,不可以在這里進行數(shù)據(jù)的網(wǎng)絡(luò)請求,否則的話有可能會導致數(shù)據(jù)網(wǎng)絡(luò)的請求重復執(zhí)行
? ? ? ? ? ? ? (d)16.3版本之后的react是異步渲染(fiber)伐割,渲染前的這個生命周期可能會被意外情況打斷候味,那么生命周期就會重新執(zhí)行 ,所以如果在這個生命周期里面執(zhí)行網(wǎng)絡(luò)請求里面隔心,可能會造成發(fā)起多次的網(wǎng)絡(luò)請求
? ? (2) componentDidMount: 掛載之后白群,在這個生命周期中有可以獲取到DOM元素、數(shù)據(jù)硬霍,一般咋這里生命周期中做數(shù)據(jù)的網(wǎng)絡(luò)請求帜慢,以及初始化swiper、better-scroll。
? ? ? ? ? (a)數(shù)據(jù)的修改不能直接引起頁面的改變粱玲,需要通過setState設(shè)置才可以
? ? ? ? ? (b)數(shù)據(jù)點修改會觸發(fā)運行中的生命周期
3. 更新階段 :
? ? (1) componentWillReceiveProps: 將要接收改變之后的props值侍咱,props里面的數(shù)據(jù)發(fā)生改變的時候觸發(fā);
? (2)? shouldComponentUpdate: 在這里判斷密幔,數(shù)據(jù)的改變是否引起頁面的改變楔脯,當沒有在代碼中寫這個函數(shù)的時候,默認返回的是true胯甩,數(shù)據(jù)改變昧廷,頁面就會發(fā)生改變,所以可以通過在這個生命周期里面判斷數(shù)據(jù)是否發(fā)生改變來決定是否需要重新更新頁面,來減少DOM操作
? ? ? (a)當在生命周期函數(shù)里面return false;// 當返回false的時候偎箫,表示數(shù)據(jù)發(fā)生改變也不改變頁面木柬,就不會再去執(zhí)行render函數(shù),渲染頁面
? ? ? (b)當在生命周期函數(shù)里面return true;// 當返回true的時候淹办,表明當數(shù)據(jù)發(fā)生改變的時候眉枕,頁面也需要發(fā)生改變,這個時候會每改變一次就執(zhí)行一次render函數(shù)渲染界面
? ? ? (c)shouldComponentUpdate(props,state): 會接收到兩個參數(shù)怜森,第一個參數(shù)是props里面數(shù)據(jù)改變的值速挑,第二個參數(shù)是state里面數(shù)據(jù)發(fā)生改變的值
(3)componentWillUpdate: 這里是組件更新之前。里面的DOM元素以及數(shù)據(jù)都是更新之前的副硅,這個生命周期也是放在render函數(shù)的前面姥宝,這個生命周期也即將被廢棄。
? ? ? 在這個生命周期中需要減少對數(shù)據(jù)進行更改的操作恐疲,否則會造成死循環(huán)腊满,因為數(shù)據(jù)已更新就會觸發(fā)這個生命周期函數(shù)
? (4) componentDidUpdate:? 組件已經(jīng)個更新完畢,在這個生命周期中需要減少對數(shù)據(jù)進行更改的操作培己,否則會造成死循環(huán)碳蛋,因為數(shù)據(jù)已更新就會觸發(fā)這個生命周期函數(shù)
4.卸載階段: componentWillUnMount:當組件銷毀的時候執(zhí)行該生命周期函數(shù)
舉個小例子
```
根組件文件
import React,{ Fragment } from 'react'
在這里引入生命周期例子的組件
import Mount from './life/Mount'
function App () {// 函數(shù)創(chuàng)建組件
return (
? <Fragment>
? ? 這里是根組件
? ? 使用組件
? ? <Mount></Mount>
? </Fragment>
)
}
export default App
```
```
子組件文件
import React,{ Component } from 'react'
class Mount extend Component {
? super()// 執(zhí)行構(gòu)造函數(shù)
? constructor() { // 構(gòu)造函數(shù)
? ? console.log('初始化',this)// 這里拿到的this就是Mount組件本身
? ? ? this.state = {
? ? ? ? name: '韓梅梅'
? ? ? }
? }
這里是組件掛載之前的生命周期
componentWillMount() {
? console.log(this)// 可以拿到組件本身
? ? cosnole.log(this.state.name) // 在這個生命周期里面可以獲取到state里面的數(shù)據(jù)
? console.log(this.refs.p)? // undefined? 這組件掛載之前的生命周期中,不能獲取到DOM元素省咨,因為這個時候虛擬DOM數(shù)據(jù)還沒有掛載到真實DOM元素上
? ? this.state.name = '李雷雷'// 這個生命周期中可以修改state里面的數(shù)據(jù)而且會使頁面發(fā)生改變肃弟,并且不會觸發(fā)進行中的生命周期
}
這個是組件掛載之后的生命周期
componentDidMount() {
? console.log(this)// 可以拿到組件本身
? cosnole.log(this.state.name) //? 這個生命周期里面可以拿到state里面的數(shù)據(jù)
? console.log(this.refs.p)? //? 這個生命周期里面可以拿到DOM元素
? this.state.name = '李雷雷'// 在這個生命周期中直接這樣更改數(shù)據(jù),頁面是不會發(fā)生改變的茸炒,因為在這個生命周期的后面愕乎,還有其他的生命周期需要執(zhí)行
? this.setState({name:'李雷雷'}) //但是可以通過setState方法來更改數(shù)據(jù)
}
這里是運行中的生命周期(state值發(fā)生改變,或者是props值發(fā)生改變 觸發(fā)shouldComponentUpDate生命周期)壁公,但是當這個生命周期存在這里的時候感论,數(shù)據(jù)發(fā)生改變之后并不一定會引起頁面的改變
里面會接收兩個參數(shù),第一個參數(shù)是props里面數(shù)據(jù)改變的值紊册,第二個參數(shù)是state里面數(shù)據(jù)發(fā)生改變的值
shouldComponentUpDate(props,state) { // 因為這個生命周期是一個疑問句的方式比肄,需要在確定快耿,當數(shù)據(jù)發(fā)生改變的時候,是否需要頁面去發(fā)生改變
? console.log('數(shù)據(jù)發(fā)生改變');
? if (this.state.name = state.name) { // 判斷state數(shù)據(jù)里面的值芳绩,與當前觸發(fā)這個生命周期拿到的參數(shù)值是否一致掀亥,一致說明state值沒有發(fā)生改變,不需要重新渲染界面
? ? return false;// 當返回false的時候妥色,表示數(shù)據(jù)發(fā)生改變也不改變頁面搪花,就不會再去執(zhí)行render函數(shù),渲染頁面
? }? else {
? ? ? return true;// 當返回true的時候嘹害,表明當數(shù)據(jù)發(fā)生改變的時候撮竿,頁面也需要發(fā)生改變,這個時候會每改變一次就執(zhí)行一次render函數(shù)渲染界面
? }
}
? render() {? //render渲染函數(shù)
? ? return (
? ? ? <div>
? ? ? ? <h1>掛載組件</h1>
? ? ? ? ? <p ref = 'p'>{this.state.name}</p>
? ? ? ? ? 給一個按鈕用來改變state里面的數(shù)據(jù)幢踏,當state值發(fā)生改變的時候就會觸發(fā)shouldComponentUpDate的生命周期,如果寫了這個生命周期许师,雖然數(shù)據(jù)會發(fā)生改變房蝉,但是頁面不會發(fā)生改變
? ? ? ? ? <button onClick = {
? ? ? ? ? ? ? this.setState({name: '李雷雷'})
? ? ? ? ? }>改值</button>
? ? </div>
? ? )
? }
這里是更新之前的生命周期函數(shù)
? componentWillUpdate () {
? ? console.log('更新之前')
? ? console.log(this)// 可以拿到組件本身
? cosnole.log(this.state.name) //? 這個生命周期里面可以拿到state里面的數(shù)據(jù)
? console.log(this.refs.p)? // 結(jié)果是<p>李雷雷</p>? 這個生命周期里面可以拿到DOM元素,但是在這里拿到的DOM元素里面渲染的數(shù)據(jù)是不真實的微渠,因為這里是更新之前恼除,數(shù)據(jù)并沒有做完更新
? console.log(this.refs.p.innerText)//結(jié)果是韓梅梅 使用innerText拿到的才是DOM元素真是的文本內(nèi)容
? }
這里是更新結(jié)束之后的生命周期函數(shù)
? componentDidUpdate () {
? ? console.log('更新結(jié)束')
? ? console.log(this)// 可以拿到組件本身
? ? cosnole.log(this.state.name) //? 這個生命周期里面可以拿到state里面的數(shù)據(jù)
? ? console.log(this.refs.p)? // 結(jié)果是<p>李雷雷</p>? 這個生命周期里面可以拿到DOM元素砸狞,但是在這里拿到的DOM元素里面渲染的數(shù)據(jù)是不真實的佑稠,因為這里是更新之前晤揣,數(shù)據(jù)并沒有做完更新
? ? console.log(this.refs.p.innerText)//結(jié)果是韓梅梅 使用innerText拿到的才是DOM元素真是的文本內(nèi)容
? }
}
export default Mount
```