React.js 小書 Lesson19 - 掛載階段的組件生命週期(二)

這一節咱們來討論一下對於一個組件來講,constructor 、componentWillMountcomponentDidMountcomponentWillUnmount 這幾個方法在一個組件的出生到死亡的過程裏面起了什麼樣的做用。javascript

通常來講,全部關於組件自身的狀態的初始化工做都會放在 constructor 裏面去作。你會發現本書全部組件的 state 的初始化工做都是放在 constructor 裏面的。假設咱們如今在作一個時鐘應用:java

React.js 小書組件的生命週期圖片

咱們會在 constructor 裏面初始化 state.date,固然如今頁面仍是靜態的,等下一會讓時間動起來。react

class Clock extends Component { constructor () { super() this.state = { date: new Date() } } render () { return ( <div> <h1> <p>如今的時間是</p> {this.state.date.toLocaleTimeString()} </h1> </div> ) } } 

一些組件啓動的動做,包括像 Ajax 數據的拉取操做、一些定時器的啓動等,就能夠放在 componentWillMount 裏面進行,例如 Ajax:git

...
  componentWillMount () {
    ajax.get('http://json-api.com/user', (userData) => { this.setState({ userData }) }) } ... 

固然在咱們這個例子裏面是定時器的啓動,咱們給 Clock 啓動定時器:github

class Clock extends Component { constructor () { super() this.state = { date: new Date() } } componentWillMount () { this.timer = setInterval(() => { this.setState({ date: new Date() }) }, 1000) } ... } 

咱們在 componentWillMount 中用 setInterval 啓動了一個定時器:每隔 1 秒更新中的 state.date,這樣頁面就能夠動起來了。咱們用一個 Index 把它用起來,而且插入頁面:ajax

class Index extends Component { render () { return ( <div> <Clock /> </div> ) } } ReactDOM.render( <Index />, document.getElementById('root') ) 

像上一節那樣,咱們修改這個 Index 讓這個時鐘能夠隱藏或者顯示:json

class Index extends Component { constructor () { super() this.state = { isShowClock: true } } handleShowOrHide () { this.setState({ isShowClock: !this.state.isShowClock }) } render () { return ( <div> {this.state.isShowClock ? <Clock /> : null } <button onClick={this.handleShowOrHide.bind(this)}> 顯示或隱藏時鐘 </button> </div> ) } } 

如今頁面上有個按鈕能夠顯示或者隱藏時鐘。你試一下顯示或者隱藏時鐘,雖然頁面上看起來功能都正常,在控制檯你會發現報錯了:api

React.js 小書組件的生命週期圖片

這是由於,當時鍾隱藏的時候,咱們並無清除定時器。時鐘隱藏的時候,定時器的回調函數還在不停地嘗試 setState,因爲 setState 只能在已經掛載或者正在掛載的組件上調用,因此 React.js 開始瘋狂報錯。閉包

屢次的隱藏和顯示會讓 React.js 從新構造和銷燬 Clock 組件,每次構造都會從新構建一個定時器。而銷燬組件的時候沒有清除定時器,因此你看到報錯會愈來愈多。並且由於 JavaScript 的閉包特性,這樣會致使嚴重的內存泄漏。less

這時候componentWillUnmount 就能夠派上用場了,它的做用就是在組件銷燬的時候,作這種清場的工做。例如清除該組件的定時器和其餘的數據清理工做。咱們給 Clock 添加 componentWillUnmount,在組件銷燬的時候清除該組件的定時器:

...
  componentWillUnmount () {
    clearInterval(this.timer) } ... 

這時候就沒有錯誤了。

總結

咱們通常會把組件的 state 的初始化工做放在 constructor 裏面去作;在 componentWillMount 進行組件的啓動工做,例如 Ajax 數據拉取、定時器的啓動;組件從頁面上銷燬的時候,有時候須要一些數據的清理,例如定時器的清理,就會放在 componentWillUnmount 裏面去作。

說一下本節沒有提到的 componentDidMount 。通常來講,有些組件的啓動工做是依賴 DOM 的,例如動畫的啓動,而 componentWillMount 的時候組件還沒掛載完成,因此無法進行這些啓動工做,這時候就能夠把這些操做放在 componentDidMount 當中。componentDidMount 的具體使用咱們會在接下來的章節當中結合 DOM 來說。

課後練習


由於第三方評論工具備問題,對本章節有任何疑問的朋友能夠移步到 React.js 小書的論壇 發帖,我會回答你們的疑問。

相關文章
相關標籤/搜索