Reactjs學習記錄(002)

State & 生命週期

狀態與屬性十分相似,但是狀態是私有的,完全受控於當前組件。

我們之前提到過,定義爲類的組件有一些特性。局部狀態就是如此:一個功能只適用於類。

將函數轉換爲類

你可以通過5個步驟將函數組件 Clock 轉換爲類

  1. 創建一個名稱擴展爲 React.Component 的ES6 類

  2. 創建一個叫做render()的空方法

  3. 將函數體移動到 render() 方法中

  4. 在 render() 方法中,使用 this.props 替換 props

  5. 刪除剩餘的空函數聲明

爲一個類添加局部狀態

我們會通過3個步驟將 date 從屬性移動到狀態中:

  1. 在 render() 方法中使用 this.state.date 替代 this.props.date
  1. 添加一個類構造函數來初始化狀態 this.state
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

類組件應始終使用props調用基礎構造函數。

將生命週期方法添加到類中

在具有許多組件的應用程序中,在銷燬時釋放組件所佔用的資源非常重要。

每當Clock組件第一次加載到DOM中的時候,我們都想生成定時器,這在React中被稱爲掛載

同樣,每當Clock生成的這個DOM被移除的時候,我們也會想要清除定時器,這在React中被稱爲卸載

我們可以在組件類上聲明特殊的方法,當組件掛載或卸載時,來運行一些代碼:

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {

  }

  componentWillUnmount() {

  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

這些方法被稱作生命週期鉤子

當組件輸出到 DOM 後會執行 componentDidMount() 鉤子,這是一個建立定時器的好地方:

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

注意我們如何在 this 中保存定時器ID。

雖然 this.props 由React本身設置以及this.state 具有特殊的含義,但如果需要存儲不用於視覺輸出的東西,則可以手動向類中添加其他字段。

如果你不在 render() 中使用某些東西,它就不應該在狀態中。

我們將在 componentWillUnmount()生命週期鉤子中卸載計時器:

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

最後,我們實現了每秒鐘執行的 tick() 方法。

它將使用 this.setState() 來更新組件局部狀態:

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

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

現在時鐘每秒鐘都會執行。

讓我們快速回顧一下發生了什麼以及調用方法的順序:

  1. 當 <Clock /> 被傳遞給 ReactDOM.render() 時,React 調用 Clock 組件的構造函數。 由於Clock 需要顯示當前時間,所以使用包含當前時間的對象來初始化 this.state 。 我們稍後會更新此狀態。

  2. React 然後調用 Clock 組件的 render() 方法。這是 React 瞭解屏幕上應該顯示什麼內容,然後 React 更新 DOM 以匹配 Clock 的渲染輸出。

  3. 當 Clock 的輸出插入到 DOM 中時,React 調用 componentDidMount() 生命週期鉤子。 在其中,Clock 組件要求瀏覽器設置一個定時器,每秒鐘調用一次 tick()

  4. 瀏覽器每秒鐘調用 tick() 方法。 在其中,Clock 組件通過使用包含當前時間的對象調用setState() 來調度UI更新。 通過調用 setState() ,React 知道狀態已經改變,並再次調用render() 方法來確定屏幕上應當顯示什麼。 這一次,render() 方法中的this.state.date 將不同,所以渲染輸出將包含更新的時間,並相應地更新DOM。

  5. 一旦Clock組件被從DOM中移除,React會調用componentWillUnmount()這個鉤子函數,定時器也就會被清除。


class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章