這一節咱們來討論一下對於一個組件來講,constructor
、componentWillMount
、componentDidMount
、componentWillUnmount
這幾個方法在一個組件的出生到死亡的過程裏面起了什麼樣的做用。html
通常來講,全部關於組件自身的狀態的初始化工做都會放在 constructor
裏面去作。你會發現本書全部組件的 state
的初始化工做都是放在 constructor
裏面的。假設咱們如今在作一個時鐘應用:ajax
咱們會在 constructor
裏面初始化 state.date
,固然如今頁面仍是靜態的,等下一會讓時間動起來。json
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:api
... componentWillMount () { ajax.get('http://json-api.com/user', (userData) => { this.setState({ userData }) }) } ...
固然在咱們這個例子裏面是定時器的啓動,咱們給 Clock
啓動定時器:閉包
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
把它用起來,而且插入頁面:ide
class Index extends Component { render () { return ( <div> <Clock /> </div> ) } } ReactDOM.render( <Index />, document.getElementById('root') )
像上一節那樣,咱們修改這個 Index
讓這個時鐘能夠隱藏或者顯示:函數
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> ) } }
如今頁面上有個按鈕能夠顯示或者隱藏時鐘。你試一下顯示或者隱藏時鐘,雖然頁面上看起來功能都正常,在控制檯你會發現報錯了:動畫
這是由於,當時鍾隱藏的時候,咱們並無清除定時器。時鐘隱藏的時候,定時器的回調函數還在不停地嘗試 setState
,因爲 setState
只能在已經掛載或者正在掛載的組件上調用,因此 React.js 開始瘋狂報錯。this
屢次的隱藏和顯示會讓 React.js 從新構造和銷燬 Clock
組件,每次構造都會從新構建一個定時器。而銷燬組件的時候沒有清除定時器,因此你看到報錯會愈來愈多。並且由於 JavaScript 的閉包特性,這樣會致使嚴重的內存泄漏。spa
這時候componentWillUnmount
就能夠派上用場了,它的做用就是在組件銷燬的時候,作這種清場的工做。例如清除該組件的定時器和其餘的數據清理工做。咱們給 Clock
添加 componentWillUnmount
,在組件銷燬的時候清除該組件的定時器:
... componentWillUnmount () { clearInterval(this.timer) } ...
這時候就沒有錯誤了。
咱們通常會把組件的 state
的初始化工做放在 constructor
裏面去作;在 componentWillMount
進行組件的啓動工做,例如 Ajax 數據拉取、定時器的啓動;組件從頁面上銷燬的時候,有時候須要一些數據的清理,例如定時器的清理,就會放在 componentWillUnmount
裏面去作。
說一下本節沒有提到的 componentDidMount
。通常來講,有些組件的啓動工做是依賴 DOM 的,例如動畫的啓動,而 componentWillMount
的時候組件還沒掛載完成,因此無法進行這些啓動工做,這時候就能夠把這些操做放在 componentDidMount
當中。componentDidMount
的具體使用咱們會在接下來的章節當中結合 DOM 來說。