若是將組件比做咱們圖中的🐜,吊繩比做🐜(組件)的壽命,吊繩左端表示🐜的出生(組件的建立),右端表示🐜的死亡(組件的銷燬)。🐜從生到死的過程會觸發吊牌上的鉤子函數執行,在
React
中咱們把組件從建立到銷燬的過程當中須要觸發的鉤子函數稱之爲生命週期函數react
React
生命週期Initalization
)setup props ande state
(設置組件的初始化屬性和狀態)static defaultProps = {
name:'計數器' //初始化默認的屬性對象
}
複製代碼
constructor(props){
super(props);
this.state = {
number:0
}
}
複製代碼
Mounting
)掛載:將虛擬DOM轉化爲真實DOM的過程ajax
componentWillMount
組件掛載以前,在渲染過程當中可能會執行屢次,不推薦使用瀏覽器
render
組件掛載架構
componentDidMount
組件掛載以後,永遠只會執行一次,推薦在此階段執行反作用,進行異步操做。好比發
ajax
請求,操做DOM
等app
Updation
)componentWillReceiveProps
組件收到新的屬性對象時調用,首次渲染不會觸發異步
shouldComponentUpdate
詢問組件是否能夠更新函數
boolean
值
true
容許更新繼續向下執行false
不容許更新,中止執行,不會調用以後的生命週期函數componentWillUpdate
組件更新以前測試
render
根據新的屬性對象從新掛載(渲染)組件ui
componentDidUpdate
組件更新完成this
shouldComponentUpdate
詢問組件是否能夠更新
boolean
值
true
容許更新繼續向下執行false
不容許更新,中止執行,不會調用以後的生命週期函數componentWillUpdate
組件更新以前
render
根據新的狀態對象從新掛載(渲染)組件
componentDilUpdtae
組件更新完成
Unmounting
)componentWillUnmount
組件卸載以前調用
有興趣的朋友能夠根據如下代碼進行測試
import React, { Component } from 'react';
/** * 父組件 */
class Counter extends Component {
static defaultProps = { //初始化默認的屬性對象
name:'計數器'
}
constructor(props) {
super(props);
this.state = { // 初始化默認的狀態對象
number:0
}
console.log('1. 父constructor初始化 props and state');
}
componentWillMount() {
console.log('2. 父componentWillMount組件將要掛載');
}
componentDidMount() {
console.log('4. 父componentDidMount組件掛載完成');
}
shouldComponentUpdate() {
console.log('5. 父componentShouldUpdate詢問組件是否能夠更新');
return true;
}
componentWillUpdate() {
console.log('6. 父componentWillUpdate組件將要更新');
}
componentDidUpdate() {
console.log('7. 父componentDidUpdate組件更新完成');
}
render() {
console.log('3. 父render渲染,也就是掛載');
const style = {display:'block'}
return (
<div style={{border:'10px solid green',pending:'10px'}}> {this.props.name}:{this.state.number} <button onClick={this.add} style={style}>+</button> {this.state.number %3 !== 0 && <SubCounter number={this.state.number}/>} </div> ); } add = () => { this.setState({ number:this.state.number+1 }) } } /** * 子組件 */ class SubCounter extends Component { static defaultProps = { number:10 } componentWillReceiveProps() { console.log('1. 子componentWillReceiveProps屬性將要發生變化 '); } shouldComponentUpdate(nextProps, nextState) { console.log('2. 子componentShouldUpdate詢問組件是否能夠更新'); // 調用此方法的時候會把新的屬性對象和新的狀態對象傳遞過來 if (nextProps.number % 3 === 0) { return true; } return false; } componentWillUnmount() { console.log(' 3.子componentWillUnmount組件將要卸載 '); } render() { return ( <div style={{border:'10px solid red'}}> {this.props.number} </div> ); } } export default Counter; 複製代碼
constructor
初始化屬性和狀態
getDerivedStateFromProps
根據屬性對象派生狀態對象
this.state.XXX
來綁定咱們的數據。示例以下import React, { Component } from 'react';
/** * 父 */
class Counter extends Component {
constructor(props) {
super(props);
this.state = {
number:0
}
}
render() {
return (
<div> <p>{this.state.number}</p> <button onClick={this.add}>+</button> <SubCounter number={this.state.number}/> </div> ); } add = () => { this.setState({ number:this.state.number+1 }) } } /** * 子 */ class SubCounter extends Component { constructor(props) { super(props); this.state = { number:0 } } static getDerivedStateFromProps(nextProps, prevState) { if (nextProps.number % 2 === 0) { return {number:nextProps.number*2} } else { return {number:nextProps.number*3} } } render() { console.log(this.state); return ( <div> <p>{this.state.number}</p> </div> ); } } export default Counter; 複製代碼
render
掛載(渲染)組件
componentDidMount
組件掛載(渲染)完成
getDerivedStateFromProps
根據屬性對象派生狀態對象
shouldComponentUpdate
詢問組件是否能夠更新
boolean
值
true
容許更新繼續向下執行false
不容許更新,中止執行,不會調用以後的生命週期函數render
根據新的狀態對象從新掛載(渲染)組件
getSnapshotbeforeUpdate
獲取更新前的快照
react
處理這個問題是很棘手的。未使用
getSnapshotbeforeUpdate
import React, { Component } from 'react';
class GetSnapshotBeforeUpdate extends Component {
constructor(props) {
super(props);
this.wrapper = React.createRef();
this.state = {
messages:['4','3','2','1','0']
}
}
componentDidMount() {
setInterval(() => {
this.setState(() => {
this.state.messages.unshift(this.state.messages.length);
}, () => {
this.setState({
messages: this.state.messages
})
})
},1000)
}
render() {
let style = {
height: '100px',
width: '200px',
border: '1px solid red',
overflow:'auto'
}
return (
<ul style={style} ref={this.wrapper}> { this.state.messages.map((message, index) => <li key={index}>{message}</li>) } </ul>
);
}
}
export default GetSnapshotBeforeUpdate;
複製代碼
使用
getSnapshotbeforeUpdate
import React, { Component } from 'react';
class GetSnapshotBeforeUpdate extends Component {
...
getSnapshotBeforeUpdate() {
// 返回更新內容的高度
return this.wrapper.current.scrollHeight;
}
// 組件更新完畢
componentDidUpdate(prevProps,prevState,prevScrollHeight) {
console.log(prevProps,prevState,prevScrollHeight);
this.wrapper.current.scrollTop = this.wrapper.current.scrollTop +
(this.wrapper.current.scrollHeight - prevScrollHeight);
}
...
export default GetSnapshotBeforeUpdate;
複製代碼
componentDidUpdate
組件更新完成
componentWillUnmount
組件卸載以前
componentDidMount
裏面調用constructor
中
constructor()
中獲取數據的話,若是時間太長,或者出錯,組件就渲染不出來,整個頁面都無法渲染了
componentWillMount()
【1】若是使用
SSR
(服務端渲染),componentWillMount
會執行2次,一次在服務端,一次在客戶端。而componentDidMount不會。
【2】
React16
以後採用了Fiber
架構,只有componentDidMount
聲明周期函數是肯定被執行一次的,相似componentWillMount
的生命週期鉤子都有可能執行屢次,因此不加以在這些生命週期中作有反作用的操做,好比請求數據之類
componentDidMount()
【1】確保已經
render
過一次。提醒咱們正確地設置初始狀態,這樣就不會獲得致使錯誤的undefined
狀態。
【2】
componentDidMount
方法中的代碼,是在組件已經徹底掛載到網頁上纔會調用被執行,因此能夠保證數據的加載。此外,在這方法中調用setState方法,會觸發重渲染。因此,官方設計這個方法就是用來加載外部數據用的,或處理其餘的反作用代碼。
componentWillMount
componentWillReceiveProps
componentWillUpdate
getDerivedStateFromProps
getSnapshotbeforeUpdate