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


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

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

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

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


這一節我們來討論一下對于一個組件來說,constructorcomponentWillMountcomponentDidMountcomponentWillUnmount 這幾個方法在一個組件的出生到死亡的過程里面起了什么樣的作用。

一般來說,所有關于組件自身的狀態的初始化工作都會放在 constructor 里面去做。你會發現本書所有組件的 state 的初始化工作都是放在 constructor 里面的。假設我們現在在做一個時鐘應用:

[圖片上傳失敗...(image-a4f288-1510226804313)]

我們會在 constructor 里面初始化 state.date,當然現在頁面還是靜態的,等下一會讓時間動起來。

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:

...
  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 把它用起來,并且插入頁面:

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>
    )
  }
}

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

[圖片上傳失敗...(image-52428a-1510226804314)]

這是因為,當時鐘隱藏的時候,我們并沒有清除定時器。時鐘隱藏的時候,定時器的回調函數還在不停地嘗試 setState,由于 setState 只能在已經掛載或者正在掛載的組件上調用,所以 React.js 開始瘋狂報錯。

多次的隱藏和顯示會讓 React.js 重新構造和銷毀 Clock 組件,每次構造都會重新構建一個定時器。而銷毀組件的時候沒有清除定時器,所以你看到報錯會越來越多。而且因為 JavaScript 的閉包特性,這樣會導致嚴重的內存泄漏。

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

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

這時候就沒有錯誤了。

總結

我們一般會把組件的 state 的初始化工作放在 constructor 里面去做;在 componentWillMount 進行組件的啟動工作,例如 Ajax 數據拉取、定時器的啟動;組件從頁面上銷毀的時候,有時候需要一些數據的清理,例如定時器的清理,就會放在 componentWillUnmount 里面去做。

說一下本節沒有提到的 componentDidMount 。一般來說,有些組件的啟動工作是依賴 DOM 的,例如動畫的啟動,而 componentWillMount 的時候組件還沒掛載完成,所以沒法進行這些啟動工作,這時候就可以把這些操作放在 componentDidMount 當中。componentDidMount 的具體使用我們會在接下來的章節當中結合 DOM 來講。

下一節中我們將介紹《React.js 小書 Lesson20 - 更新階段的組件生命周期》

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容