React.js 小書 Lesson18 - 掛載階段的組件生命周期(一)


React.js 小書 Lesson18 - 掛載階段的組件生命周期(一)

本文作者:胡子大哈
本文原文:http://huziketang.com/books/react/lesson18

轉(zhuǎn)載請注明出處,保留原文鏈接以及作者信息

在線閱讀:http://huziketang.com/books/react


我們在講解 JSX 的章節(jié)中提到,下面的代碼:

ReactDOM.render(
 <Header />, 
  document.getElementById('root')
)

會編譯成:

ReactDOM.render(
  React.createElement(Header, null), 
  document.getElementById('root')
)

其實(shí)我們把 Header 組件傳給了 React.createElement 函數(shù),又把函數(shù)返回結(jié)果傳給了 ReactDOM.render。我們可以簡單猜想一下它們會干什么事情:

// React.createElement 中實(shí)例化一個 Header
const header = new Header(props, children)
// React.createElement 中調(diào)用 header.render 方法渲染組件的內(nèi)容
const headerJsxObject = header.render()

// ReactDOM 用渲染后的 JavaScript 對象來來構(gòu)建真正的 DOM 元素
const headerDOM = createDOMFromObject(headerJsxObject)
// ReactDOM 把 DOM 元素塞到頁面上
document.getElementById('root').appendChild(headerDOM)

上面過程其實(shí)很簡單,看代碼就能理解。

我們把 React.js 將組件渲染,并且構(gòu)造 DOM 元素然后塞入頁面的過程稱為組件的掛載(這個定義請好好記?。F鋵?shí) React.js 內(nèi)部對待每個組件都有這么一個過程,也就是初始化組件 -> 掛載到頁面上的過程。所以你可以理解一個組件的方法調(diào)用是這么一個過程:

-> constructor()
-> render()
// 然后構(gòu)造 DOM 元素插入頁面

這當(dāng)然是很好理解的。React.js 為了讓我們能夠更好的掌控組件的掛載過程,往上面插入了兩個方法:

-> constructor()
-> componentWillMount()
-> render()
// 然后構(gòu)造 DOM 元素插入頁面
-> componentDidMount()

componentWillMountcomponentDidMount 都是可以像 render 方法一樣自定義在組件的內(nèi)部。掛載的時候,React.js 會在組件的 render 之前調(diào)用 componentWillMount,在 DOM 元素塞入頁面以后調(diào)用 componentDidMount。

我們給 Header 組件加上這兩個方法,并且打一些 Log:

class Header extends Component {
  constructor () {
    super()
    console.log('construct')
  }

  componentWillMount () {
    console.log('component will mount')
  }

  componentDidMount () {
    console.log('component did mount')
  }

  render () {
    console.log('render')
    return (
      <div>
        <h1 className='title'>React 小書</h1>
      </div>
    )
  }
}

在控制臺你可以看到依次輸出:

[圖片上傳失敗...(image-427c29-1510226757139)]

可以看到,React.js 確實(shí)按照我們上面所說的那樣調(diào)用了定義的兩個方法 componentWillMountcomponentDidMount

機(jī)靈的同學(xué)可以想到,一個組件可以插入頁面,當(dāng)然也可以從頁面中刪除。

-> constructor()
-> componentWillMount()
-> render()
// 然后構(gòu)造 DOM 元素插入頁面
-> componentDidMount()
// ...
// 從頁面中刪除

React.js 也控制了這個組件的刪除過程。在組件刪除之前 React.js 會調(diào)用組件定義的 componentWillUnmount

-> constructor()
-> componentWillMount()
-> render()
// 然后構(gòu)造 DOM 元素插入頁面
-> componentDidMount()
// ...
// 即將從頁面中刪除
-> componentWillUnmount()
// 從頁面中刪除

看看什么情況下會把組件從頁面中刪除,繼續(xù)使用上面例子的代碼,我們再定義一個 Index 組件:

class Index extends Component {
  constructor() {
    super()
    this.state = {
      isShowHeader: true
    }
  }

  handleShowOrHide () {
    this.setState({
      isShowHeader: !this.state.isShowHeader
    })
  }

  render () {
    return (
      <div>
        {this.state.isShowHeader ? <Header /> : null}
        <button onClick={this.handleShowOrHide.bind(this)}>
          顯示或者隱藏標(biāo)題
        </button>
      </div>
    )
  }
}

ReactDOM.render(
  <Index />,
  document.getElementById('root')
)

Index 組件使用了 Header 組件,并且有一個按鈕,可以控制 Header 的顯示或者隱藏。下面這行代碼:

...
{this.state.isShowHeader ? <Header /> : null}
...

相當(dāng)于 state.isShowHeadertrue 的時候把 Header 插入頁面,false 的時候把 Header 從頁面上刪除。這時候我們給 Header 添加 componentWillUnmount 方法:

...
  componentWillUnmount() {
    console.log('component will unmount')
  }
...

這時候點(diǎn)擊頁面上的按鈕,你會看到頁面的標(biāo)題隱藏了,并且控制臺打印出來下圖的最后一行,說明 componentWillUnmount 確實(shí)被 React.js 所調(diào)用了:

[圖片上傳失敗...(image-5cf4c5-1510226757139)]

你可以多次點(diǎn)擊按鈕,隨著按鈕的顯示和隱藏,上面的內(nèi)容會按順序重復(fù)地打印出來,可以體會一下這幾個方法的調(diào)用過程和順序。

總結(jié)

React.js 將組件渲染,并且構(gòu)造 DOM 元素然后塞入頁面的過程稱為組件的掛載。這一節(jié)我們學(xué)習(xí)了 React.js 控制組件在頁面上掛載和刪除過程里面幾個方法:

  • componentWillMount:組件掛載開始之前,也就是在組件調(diào)用 render 方法之前調(diào)用。
  • componentDidMount:組件掛載完成以后,也就是 DOM 元素已經(jīng)插入頁面后調(diào)用。
  • componentWillUnmount:組件對應(yīng)的 DOM 元素從頁面中刪除之前調(diào)用。

但這一節(jié)并沒有講這幾個方法到底在實(shí)際項(xiàng)目當(dāng)中有什么作用,下一節(jié)我們通過例子來講解一下這幾個方法的用途。

下一節(jié)中我們將介紹《React.js 小書 Lesson19 - 掛載階段的組件生命周期(二)》。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容