什么时候使用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`方法中建立一个新的函数,对象或者是数组那么你的作法(可能)是错误的。
相关文章
相关标签/搜索