React組件的生命週期,主要分爲掛載、更新以及移除階段的生命週期。所謂掛載指的是組件從初始化到渲染到頁面的過程。卸載指的是組件生成的DOM元素從頁面中刪除的過程。更新指的是組件更新的過程。那麼在這些過程當中它都經歷了些什麼呢?
首先來一段代碼:
ReactDOM.render(
<Book/>
document.querySelector("#wrap")
)
其實以上代碼在經過React.js的編譯後會變成這個樣子:
ReactDOM.render(
// <Book/>,
React.createElement(Book),
document.querySelector("#wrap")
)
也就是說將Book傳給了React.createElement函數,又將該函數的結果返回給了ReactDOM.rende。最後將組件掛載到了id爲wrap的元素中!我們也可以大膽的猜測一下在這個過程中它都做了些什麼事:
// React.createElement 中實例化一個 Book
const book = new Book(props, children)
// React.createElement 中調用 book.render 方法渲染組件的內容
const bookJsxObject = book.render()
// ReactDOM 用渲染後的 JavaScript 對象來來構建真正的 DOM 元素
const bookDOM = createDOMFromObject(bookJsxObject)
// ReactDOM 把 DOM 元素塞到頁面上
document.querySelector("#wrap").innerHTML=bookDOM;
以上代碼也可以簡單理解爲:
// 實例化組件,也就是構造DOM元素
constructor();
// 將構造的元素插入到指定的頁面元素中
render();
不過在掛載的過程當中,其實還有兩個方法,分別爲componentWillMount 和 componentDidMount。
// 實例化組件,也就是構造DOM元素
constructor();
// 當DOM元素載入之前調用
componentWillMount();
// 將構造的元素插入到指定的頁面元素中
render();
// 當DOM元素載入頁面之後調用
componentDidMount();
componentWillMount方法在組件掛載到頁面之前調用。而componentDidMount方法是在掛載到頁面以後調用。我們也可以將這兩個方法放到組件內部:
class Book extends React.Component{
constructor(){
super();
console.log("執行constructor");
}
componentWillMount(){
console.log("執行componentWillmount");
}
componentDidMount(){
console.log("執行componentDidMount");
}
render(){
console.log("執行render");
return (
<div>大家好,我叫張培躍</div>
)
}
}
ReactDOM.render(
<Book/>,
document.querySelector("#wrap")
)
通過以上示例的輸出結果,我們也可以看到方法的執行順序:
->執行constructor
->執行componentWillmount
->執行render
->執行componentDidMount
componentWillmount在render之前,componentDidMount在render之後
接下來咱們再來思考一個問題,我們既然可以將組件掛載到頁面中,自然也可以將組件在頁面中進行卸載。而當組件卸載之前會調用組件的componentWillUnmount方法:
// 實例化組件,也就是構造DOM元素
constructor();
// 當DOM元素載入之前調用
componentWillMount();
// 將構造的元素插入到指定的頁面元素中
render();
// 當DOM元素載入頁面之後調用
componentDidMount();
// 當從頁面中卸載時會調用
componentWillUnmount()
接下來,我們再來定義一個組件,讓該組件控制對Book組件的掛載與卸載:
class My extends React.Component{
constructor(){
super();
this.state={
isShow:true
};
this.changeIsShow=this.changeIsShow.bind(this);
}
changeIsShow(){
this.setState({
isShow:!this.state.isShow
})
}
render(){
return (
<div>
<input type="button" value="點我啊"
onClick={this.changeIsShow}/>
{/*根據isShow來對Book進行掛載與卸載*/}
{this.state.isShow?<Book />:null}
</div>
)
}
}
ReactDOM.render(
<My/>,
document.querySelector("#wrap")
)
然後在在Book組件中增加componentWillUnmount方法:
class Book extends React.Component{
constructor(){
super();
console.log("執行constructor");
}
componentWillMount(){
console.log("執行componentWillmount");
}
componentDidMount(){
console.log("執行componentDidMount");
}
componentWillUnmount(){
console.log("執行componentWillUnmount");
}
render(){
console.log("執行render");
return (
<div>大家好,我叫張培躍</div>
)
}
}
當點擊按鈕時控制檯會輸出最後一行,說明componentWillUnmount方法在被卸載時調用了:
->執行constructor
->執行componentWillmount
->執行render
->執行componentDidMount
完整示例代碼:
class Book extends React.Component{
constructor(){
super();
console.log("執行constructor");
}
componentWillMount(){
console.log("執行componentWillmount");
}
componentDidMount(){
console.log("執行componentDidMount");
}
componentWillUnmount(){
console.log("執行componentWillUnmount");
}
render(){
console.log("執行render");
return (
<div>大家好,我叫張培躍</div>
)
}
}
class My extends React.Component{
constructor(){
super();
this.state={
isShow:true
};
this.changeIsShow=this.changeIsShow.bind(this);
}
changeIsShow(){
this.setState({
isShow:!this.state.isShow
})
}
render(){
return (
<div>
<input type="button" value="點我啊"
onClick={this.changeIsShow}/>
{/*根據isShow來對Book進行掛載與卸載*/}
{this.state.isShow?<Book />:null}
</div>
)
}
}
ReactDOM.render(
<My/>,
document.querySelector("#wrap")
)
到目前爲止,咱們已經見證了組件從出生到死亡的一個過程!接下來我們一起通過一個計數器的實例來了解這些函數的作用!
現在我們要完成一個倒計時的小應用,如下:
首先通過constructor進行初始化:
class AddOne extends React.Component{
constructor(){
super();
//設置初始值
this.state={
num:0,
timer:null
}
}
componentWillMount(){
// 組件掛載時添加計數器
this.timer=setInterval(()=>{
this.setState({
num:this.state.num+1
})
},1000)
}
componentWillUnmount(){
// 組件卸載時移除計數器
clearInterval(this.timer);
}
render(){
return (
<div>
<h1>{this.state.num}</h1>
</div>
)
}
}
class Start extends React.Component{
constructor(){
super();
this.state={
isShow:false
};
this.changeIsShow=this.changeIsShow.bind(this);
}
changeIsShow(){
this.setState({
isShow:!this.state.isShow
})
}
render(){
return (
<div>
<input type="button" value={this.state.isShow?"結束":"開始計時"} onClick={this.changeIsShow}/>
{this.state.isShow?<AddOne />:null}
</div>
);
}
}
ReactDOM.render(
<Start/>,
document.querySelector("#wrap")
)
小結一下:
- componentWillMount:在組件調用 render 方法之前調用。
- componentDidMount:是 DOM 元素已經插入頁面後調用。
- componentWillUnmount:組件對應的 DOM 元素從頁面中卸載之前調用。
未完,等續