什麼時候使用Component仍是PureComponent?

原文: When to use Component or PureComponent?

什麼時候使用Component仍是PureComponent?

我開始轉向使用PureCompoent是由於它是一個更具性能的Component的版本。雖然事實證實這是正確的,可是這種性能的提升還伴隨着一些附加的條件。讓咱們深挖一下PureComponent,並理解爲何咱們應該使用它。javascript

Component和PureComponent有一個不一樣點

除了爲你提供了一個具備淺比較的shouldComponentUpdate方法,PureComponentComponent基本上徹底相同。當props或者state改變時,PureComponent將對propsstate進行淺比較。另外一方面,Component不會比較當前和下個狀態的propsstate。所以,每當shouldComponentUpdate被調用時,組件默認的會從新渲染。java

淺比較101

當把以前和下一個的propsstate做比較,淺比較將檢查原始值是否有相同的值(例如:1 == 1或者ture==true),數組和對象引用是否相同。git

從不改變

您可能已經據說過,不要在propsstate中改變對象和數組,若是你在你的父組件中改變對象,你的「pure」子組件不將更新。雖然值已經被改變,可是子組件比較的是以前props的引用是否相同,因此不會檢測到不一樣。es6

所以,你能夠經過使用es6的assign方法或者數組的擴展運算符或者使用第三方庫,強制返回一個新的對象。github

存在性能問題?

比較原始值值和對象引用是低耗時操做。若是你有一列子對象而且其中一個子對象更新,對它們的propsstate進行檢查要比從新渲染每個子節點要快的多。redux

其它解決辦法

不要在render的函數中綁定值

假設你有一個項目列表,每一個項目都傳遞一個惟一的參數到父方法。爲了綁定參數,你可能會這麼作:數組

<CommentItem likeComment={() => this.likeComment(user.id)} />

這個問題會致使每次父組件render方法被調用時,一個新的函數被建立,已將其傳入likeComment。這會有一個改變每一個子組件props的反作用,它將會形成他們所有從新渲染,即便數據自己沒有發生變化。緩存

爲了解決這個問題,只須要將父組件的原型方法的引用傳遞給子組件。子組件的likeComment屬性將老是有相同的引用,這樣就不會形成沒必要要的從新渲染。安全

<CommentItem likeComment={this.likeComment} userID={user.id} />

而後再子組件中建立一個引用了傳入屬性的類方法:函數

class CommentItem extends PureComponent {
  ...
  handleLike() {
    this.props.likeComment(this.props.userID)
  }
  ...
}

不要在render方法裏派生數據

考慮一下你的配置組件將從一系列文章中展現用戶最喜歡的十篇文章。

render() {
  const { posts } = this.props
  const topTen = posts.sort((a, b) => b.likes - a.likes).slice(0, 9)
  return //...
}

每次組件從新渲染時topTen都將有一個新的引用,即便posts沒有改變而且派生數據也是相同的。這將形成列表沒必要要的從新渲染。

你能夠經過緩存你的派生數據來解決這個問題。例如,設置派生數據在你的組件state中,僅當posts更新時它才更新。

componentWillMount() {
  this.setTopTenPosts(this.props.posts)
}
componentWillReceiveProps(nextProps) {
  if (this.props.posts !== nextProps.posts) {
    this.setTopTenPosts(nextProps)
  }
}
setTopTenPosts(posts) {
  this.setState({
    topTen: posts.sort((a, b) => b.likes - a.likes).slice(0, 9)
  })
}

若是你正在使用Redux,能夠考慮使用reselect來建立"selectors"來組合和緩存派生數據。

結束語

只要你遵循下列兩個簡單的規則就能夠安全的使用PureComponent來代替Component:

- 雖然一般狀況下易變性就是很差的,可是當使用`PureComponent`時問題會變得複雜。
- 若是你在`render`方法中建立一個新的函數,對象或者是數組那麼你的作法(可能)是錯誤的。
相關文章
相關標籤/搜索