生命周期 & State

2020-05-12 17:46 更新

在本節(jié)中,我們將學(xué)習(xí)如何重用和封裝一個 Clock 組件。它將設(shè)置自己的計時器,并每秒鐘更新一次。

我們可以從封裝時鐘開始:

class Clock extends Component {
  render () {
    return (
      <View>
        <Text>Hello, world!</Text>
        <Text>現(xiàn)在的時間是 {this.state.date.toLocaleTimeString()}.</Text>
      </View>
    )
  }
}

Clock 現(xiàn)在被定義為一個類,使用類就允許我們使用其它特性,例如局部狀態(tài)、生命周期鉤子。

為一個類添加局部狀態(tài)

首先,我們需要添加一個類構(gòu)造函數(shù)來初始化狀態(tài) this.state:

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

  render () {
    return (
      <View>
        <Text>Hello, world!</Text>
        <Text>現(xiàn)在的時間是 {this.state.date.toLocaleTimeString()}.</Text>
      </View>
    )
  }
}

注意我們?nèi)绾蝹鬟f props 到基礎(chǔ)構(gòu)造函數(shù)的:

constructor (props) {
  super(props)
  this.state = { date: new Date() }
}

類組件應(yīng)始終使用 props 調(diào)用基礎(chǔ)構(gòu)造函數(shù)。 接下來,我們將使 Clock 設(shè)置自己的計時器并每秒更新一次。

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

在具有許多組件的應(yīng)用程序中,在銷毀時釋放組件所占用的資源非常重要。

每當(dāng) Clock 組件第一次加載到 DOM 中的時候,我們都想生成定時器,這在 Taro/React 中被稱為掛載。

同樣,每當(dāng) Clock 生成的這個 DOM 被移除的時候,我們也會想要清除定時器,這在 Taro/React 中被稱為卸載。

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

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

  componentDidMount() {

  }

  componentWillUnmount() {

  }

  render () {
    return (
      <View>
        <Text>Hello, world!</Text>
        <Text>現(xiàn)在的時間是 {this.state.date.toLocaleTimeString()}.</Text>
      </View>
    )
  }
}

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

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

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

注意我們?nèi)绾卧?this 中保存定時器 ID。

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

如果你不在 render() 中使用某些東西,它就不應(yīng)該在狀態(tài)中。

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

componentWillUnmount () {
  clearInterval(this.timerID)
}

最后,我們實現(xiàn)了每秒鐘執(zhí)行的 tick() 方法。

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

import Taro, { Component } from '@tarojs/taro'

class Clock extends 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 (
      <View>
        <Text>Hello, world!</Text>
        <Text>現(xiàn)在的時間是 {this.state.date.toLocaleTimeString()}.</Text>
      </View>
    )
  }
}

正確地使用 State

關(guān)于 setState() 這里有三件事情需要知道:

不要直接更新狀態(tài)

例如,此代碼不會重新渲染組件:

// Wrong
this.state.comment = 'Hello'

應(yīng)當(dāng)使用 setState():

// Correct
this.setState({ comment: 'Hello' })

setState() 函數(shù)是唯一能夠更新 this.state 的地方。

狀態(tài)更新一定是異步的

Taro 可以將多個 setState() 調(diào)用合并成一個調(diào)用來提高性能。

因為 this.state 和 props 一定是異步更新的,所以你不能在 setState 馬上拿到 state 的值,例如:

// 假設(shè)我們之前設(shè)置了 this.state.counter = 0
updateCounter () {
  this.setState({
    counter: 1
  })
  console.log(this.state.counter) // 這里 counter 還是 0
}

正確的做法是這樣,在 setState 的第二個參數(shù)傳入一個 callback:

// 假設(shè)我們之前設(shè)置了 this.state.counter = 0
updateCounter () {
  this.setState({
    counter: 1
  }, () => {
    // 在這個函數(shù)內(nèi)你可以拿到 setState 之后的值
  })
}
這是 Taro 和 React 另一個不同的地方:React 的 setState 不一定總是異步的,他內(nèi)部有一套事務(wù)機制控制,且 React 15/16 的實現(xiàn)也各不相同。而對于 Taro 而言,setState 之后,你提供的對象會被加入一個數(shù)組,然后在執(zhí)行下一個 eventloop 的時候合并它們。

state 更新會被合并

當(dāng)你調(diào)用 setState(),Taro 將合并你提供的對象到當(dāng)前的狀態(tài)中。

例如,你的狀態(tài)可能包含幾個獨立的變量:

constructor(props) {
  super(props)
  this.state = {
    posts: [],
    comments: []
  }
}

然后通過調(diào)用獨立的 setState() 調(diào)用分別更新它們:

componentDidMount() {
  fetchPosts().then(response => {
    this.setState({
      posts: response.posts
    });
  });

  fetchComments().then(response => {
    this.setState({
      comments: response.comments
    })
  })
}

合并是淺合并,所以 this.setState({comments}) 不會改變 this.state.posts 的值,但會完全替換 this.state.comments 的值。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號