资讯专栏INFORMATION COLUMN

何时使用Component还是PureComponent?

EdwardUp / 2420人阅读

摘要:原文何时使用还是我开始转向使用是因为它是一个更具性能的的版本。存在性能问题比较原始值值和对象引用是低耗时操作。这会有一个改变每个子组件的副作用,它将会造成他们全部重新渲染,即使数据本身没有发生变化。

原文:When to use Component or PureComponent?
何时使用Component还是PureComponent?

我开始转向使用PureCompoent是因为它是一个更具性能的Component的版本。虽然事实证明这是正确的,但是这种性能的提高还伴随着一些附加的条件。让我们深挖一下PureComponent,并理解为什么我们应该使用它。

Component和PureComponent有一个不同点

除了为你提供了一个具有浅比较的shouldComponentUpdate方法,PureComponentComponent基本上完全相同。当props或者state改变时,PureComponent将对propsstate进行浅比较。另一方面,Component不会比较当前和下个状态的propsstate。因此,每当shouldComponentUpdate被调用时,组件默认的会重新渲染。

浅比较101

当把之前和下一个的propsstate作比较,浅比较将检查原始值是否有相同的值(例如:1 == 1或者ture==true),数组和对象引用是否相同。

从不改变

您可能已经听说过,不要在propsstate中改变对象和数组,如果你在你的父组件中改变对象,你的“pure”子组件不将更新。虽然值已经被改变,但是子组件比较的是之前props的引用是否相同,所以不会检测到不同。

因此,你可以通过使用es6的assign方法或者数组的扩展运算符或者使用第三方库,强制返回一个新的对象。

存在性能问题?

比较原始值值和对象引用是低耗时操作。如果你有一列子对象并且其中一个子对象更新,对它们的propsstate进行检查要比重新渲染每一个子节点要快的多。

其它解决办法 不要在render的函数中绑定值

假设你有一个项目列表,每个项目都传递一个唯一的参数到父方法。为了绑定参数,你可能会这么做:

 this.likeComment(user.id)} />

这个问题会导致每次父组件render方法被调用时,一个新的函数被创建,已将其传入likeComment。这会有一个改变每个子组件props的副作用,它将会造成他们全部重新渲染,即使数据本身没有发生变化。

为了解决这个问题,只需要将父组件的原型方法的引用传递给子组件。子组件的likeComment属性将总是有相同的引用,这样就不会造成不必要的重新渲染。

然后再子组件中创建一个引用了传入属性的类方法:

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`方法中创建一个新的函数,对象或者是数组那么你的做法(可能)是错误的。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95194.html

相关文章

  • Component,PureComponent源码解析

    摘要:首先是创建了一个构造函数,他的原型指到的原型然后创建了一个加上了和一样的属性这里为啥不用。的原型指向的实例修改原型的属性使其正确指向的构造函数,并挂一个的属性。 每次都信誓旦旦的给自己立下要好好学习react源码的flag,结果都是因为某个地方卡住了,或是其他原因没看多少就放弃了。这次又给自己立个flag-坚持看完react源码。为了敦促自己,特开设这样一个专栏来记录自己的学习历程,这...

    luqiuwen 评论0 收藏0
  • 使用React.memo()来优化函数组件的性能

    摘要:函数组件上面我们探讨了如何使用和的方法优化类组件的性能。它的作用和类似,是用来控制函数组件的重新渲染的。其实就是函数组件的。 原文链接: Improving Performance in React Functional Component using React.memo 原文作者: Chidume Nnamdi 译者: 进击的大葱 推荐理由: 本文讲述了开发React应用时如...

    BetaRabbit 评论0 收藏0
  • React 最佳实践

    摘要:本文针对技术栈,总结了一些最佳实践,对编写高质量的代码有一定的参考作用。二最佳实践说明多用如果组件是纯展示型的,不需要维护和生命周期,则优先使用。理解并遵循这些最佳实践,写出来的代码质量会有一定的保证。 欢迎关注我的公众号睿Talk,获取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、前言 在日常开发和 Code Revi...

    lavnFan 评论0 收藏0
  • React源码解析之React.Component()/PureComponent()

    摘要:只涉及了,其他均没有自己实现。这种组件的复用性是最强的。所以会新建,只继承的原型,不包括,以此来节省内存。 showImg(https://segmentfault.com/img/remote/1460000019783989); 一、React.Component() GitHub:https://github.com/AttackXiaoJinJin/reactExplain/...

    Cristalven 评论0 收藏0
  • 谈一谈创建React Component的几种方式

    摘要:用这种方式创建组件时,并没有对内部的函数,进行绑定,所以如果你想让函数在回调中保持正确的,就要手动对需要的函数进行绑定,如上面的,在构造函数中对进行了绑定。 当我们谈起React的时候,多半会将注意力集中在组件之上,思考如何将页面划分成一个个组件,以及如何编写可复用的组件。但对于接触React不久,还没有真正用它做一个完整项目的人来说,理解如何创建一个组件也并不那么简单。在最开始的时候...

    mylxsw 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<