一共有四個聲明周期init(初始化),mount(裝載),update(更新),unmount(卸載)。只有更新可能會執(zhí)行多次,其余都只執(zhí)行1次。
init
getDefaultProps(生成默認(rèn)屬性):在創(chuàng)建類的時候,React.createclass時指定。是一個共有的,所有的實例都會使用,是針對類而言的,只會調(diào)用一次。
getInitialState(初始化state):ES6時在構(gòu)造函數(shù)中指定。getInitialState針對具體的實例,每個實例生成時都會調(diào)用一次。
const Item = React.createClass({
getDefaultProps () {
console.log('getDefaultProps')
return {
'group': 'javascript'
}
},
getInitialState () {
console.log('getInitialState')
return {
'name': 'cc'
}
},
render () {
return <div>{this.state.name + this.props.group}</div>
}
})
ReactDOM.render(
<div>
<Item />
</div>, document.getElementById('root'))

執(zhí)行的先后順序。當(dāng)調(diào)用多個item時:
ReactDOM.render(
<div>
<Item />
<Item />
<Item />
</div>, document.getElementById('root'))

調(diào)用了一次getDefaultProps,三次getInitialState。
mount組件裝載階段:包含預(yù)加載、渲染和加載完畢三個周期,都只執(zhí)行一次。預(yù)加載時dom未成形,不能操作dom。
class Item extends React.Component {
constructor (props) {
super(props)
console.log('getInitialState')
this.state = {
'group': 'hello'
}
}
static get defaultProps () {
console.log('defaultProps')
return {
'name': 'cc'
}
}
componentWillMount () {
console.log('componentWillMount')
this.state.name = 'cc'
}
componentDidMount () {
console.log('componentDidMount')
}
render () {
console.log('render')
return <div>{this.state.group + this.props.name}</div>
}
}
打印順序如下圖

componentWillMount(預(yù)加載),可以操作組件的state,不能操作DOM。
componentDidMount(加載完畢),這時可以操作DOM,也可以再此處引入一些外部交互,比如發(fā)送請求,與其他框架交互。
render(渲染),初次渲染,沒什么好說的。
Update:只在組件更新時會觸發(fā),初次加載時不會觸發(fā)。
把上面的代碼頁面渲染部分封裝為render方法:
const Item = React.createClass({
getDefaultProps () {
console.log('getDefaultProps')
return {
'group': 'javascript'
}
},
getInitialState () {
console.log('getInitialState')
return {
'name': 'cc'
}
},
componentWillMount () {
console.log('componentWillMount')
this.state.name = 'cc'
},
componentDidMount () {
console.log('componentDidMount')
},
render () {
console.log('render')
return <div>{this.state.group + this.props.name}</div>
},
componentWillUpdate (nextProps, nextState) {
console.log('component will update')
},
componentDidUpdate (oldProps, oldState) {
console.log('compontent did update')
}
})
ReactDOM.render(
<div>
<Item />
</div>, document.getElementById('root'))

初次加載沒有觸發(fā)update,觸發(fā)update有三種方式,外部渲染(如本例中演示),內(nèi)部state變化,外部傳入?yún)?shù)。當(dāng)我們頁面的render方法包裝下。
function render () {
ReactDOM.render(
<div>
<Item />
</div>, document.getElementById('root'))
}
render() //調(diào)用兩次render
render()

觸發(fā)了update,而且每次還會自動調(diào)用render。
componentWillUpdate(nextProps,nextState):組件預(yù)更新,接受兩個參數(shù),新的組件props和新的狀態(tài)state;
為了防止組件頻繁刷新,還有一個組件的更新驗證方法shouldComponentUpdate,用于控制組件是否需要更新狀態(tài)。
特殊方法: shouldComponentUpdate (nextProps, nextState) {
return false//返回false,則組件不會被update
}

組件加入shouldComponentUpdate 后沒有被update。
特殊方法:componentWillReceiveProps(nextProps)已加載組件收到新的參數(shù)時調(diào)用。componentWillReceiveProps()
當(dāng)一個組件收到新的props時被調(diào)用。如果需要改變狀態(tài)來響應(yīng)props的改變可以先比較傳入的props和當(dāng)前的props,再在此方法內(nèi)調(diào)用setState()來改變state。React可能會調(diào)用這個方法,即使props沒有改變,所以在處理變化時必須在方法內(nèi)比較當(dāng)前值和新的值props。這個可能會因為父元素的變化導(dǎo)致子元素重新渲染。在組件加載過程中不會調(diào)用此方法。只有傳入新的props時才會調(diào)用,同樣setState也不會觸發(fā)此方法。(以上翻自react官網(wǎng)說明)。
unmount卸載階段
componentWillUnmount
在組件被卸載和摧毀前被立即調(diào)用。清理應(yīng)該放在這里。
比如說我在組件的加載時寫了個setInterval定時器,在路由router跳轉(zhuǎn)后,我們應(yīng)該要clearInterval這個定時器,不然是很耗性能的,包括我們的全局事件綁定,都需要在這里取消。
.