Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >React Native之PureComponent

React Native之PureComponent

作者头像
VV木公子
发布于 2020-02-18 09:14:50
发布于 2020-02-18 09:14:50
7.6K00
代码可运行
举报
文章被收录于专栏:TechBoxTechBox
运行总次数:0
代码可运行

前言

PureComponent继承自Component。PureComponent几乎和Component完全相同。

唯一不同之处在于Component的shouldComponentUpdate的默认实现是返回true。而PureComponent通过props和state的浅比较实现shouldComponentUpdate,某些情况下使用PureComponent可以减少不必要的渲染,提升性能。

PureComponent原理

之所以,Components的props和state每次发生变化时都会触发render。是因为Component的shouldComponentUpdate方法默认返回了true。而PureComponent的shouldComponentUpdate并非简单的返回了true。

当PureComponent组件更新时,如果组件的 props 和 state 都没发生改变, render 方法就不会触发,省去 Virtual DOM 的生成和比对过程,达到提升性能的目的。具体就是 React 自动帮我们做了一层浅比较shallowEqual(即指针比较),如下是PureComponent的shouldComponentUpdate的源码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (this._compositeType === CompositeTypes.PureClass) {
  shouldUpdate = !shallowEqual(prevProps, nextProps)
  || !shallowEqual(inst.state, nextState);
}

关于浅比较的更多内容可以参考https://www.imweb.io/topic/598973c2c72aa8db35d2e291

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

PureComponent注意事项

1.可变数据变化前后不能使用同一个引用。 2.不变数据变化前后需使用同一个引用。

具体解释

1> 使用PureComponent不要在props和state中改变对象和数组这种引用类型。即可变数据不能使用同一个引用。如果你在你的父组件中改变对象,你的“pure”子组件不将更新。虽然值已经被改变,但是子组件比较的是之前props的引用是否相同,所以不会检测到不同。因此,你可以通过使用es6的assign方法或者数组的扩展运算符或者使用第三方库,强制返回一个新的对象。

2> 不要在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) } ... }

3> 不要在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"来组合和缓存派生数据。

4> 子组件数据更新,使用Immutable.js库解决数据不变问题。

有时候数组或对象内部依旧持有的是数组或对象,数据引用变化,虽然指针变了,但是内层数据实际上没变化,此时也会触发render。这个时候可以使用immutable-js函数库。

5> 复杂状态与简单状态不要共用一个组件

这点可能和 PureComponent 没多少关系,但做的不好可能会浪费很多性能,比如一个页面上面一部分是一个复杂的列表,下面是一个输入框,抽象代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
change = (e) => {
  this.setState({ value: e.target.value });
}
render() {
  return (<div>
    <ul>
      {this.state.items.map((i, k) => <li key={k}> {...}</li>)}
    </ul>
    <input value={this.state.value} onChange={this.change} />
  </div>)
}

表单和列表其实是没有什么关联的,表单的值也可能经常变动,但它的会给列表也带来必然的 diff操作,这是没必要的,最好是给列表抽出成一个单独的 PureComponent 组件,这样 state.items不变的话,列表就不会重新 render 了。

PureComponent与shouldComponentUpdate共存

如果 PureComponent 里有 shouldComponentUpdate 函数的话,直接使用 shouldComponentUpdate 的结果作为是否更新的依据,没有 shouldComponentUpdate 函数的话,才会去判断是不是 PureComponent ,是的话再去做 shallowEqual 浅比较。

原则

  1. 虽然通常情况下易变性就是不好的,但是当使用PureComponent时问题会变得复杂。尽量让数据不可变,可以使用Immutable.js。
  2. 如果你在render方法中创建一个新的函数、对象或者是数组,那么你的做法(可能)是错误的。
  3. PureComponent不仅会影响本身,而且会影响子组件,所以PureComponent最佳情况是展示组件。(关于展示组件可以参考https://juejin.im/post/5a52fe32f265da3e317e008bhttps://juejin.im/post/5af3d66ef265da0b7b35ec1d

浅比较

shallowEqual会比较 Object.keys(state | props) 的长度是否一致,每一个 key 是否两者都有,并且是否是一个引用,也就是只比较了第一层的值,确实很浅,所以深层的嵌套数据是对比不出来的。

shallowEqual源码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const hasOwn = Object.prototype.hasOwnProperty

function is(x, y) {
  if (x === y) {
    return x !== 0 || y !== 0 || 1 / x === 1 / y
  } else {
    return x !== x && y !== y
  }
}

export default function shallowEqual(objA, objB) {
  if (is(objA, objB)) return true

  if (typeof objA !== 'object' || objA === null ||
      typeof objB !== 'object' || objB === null) {
    return false
  }

  const keysA = Object.keys(objA)
  const keysB = Object.keys(objB)

  if (keysA.length !== keysB.length) return false

  for (let i = 0; i < keysA.length; i++) {
    if (!hasOwn.call(objB, keysA[i]) ||
        !is(objA[keysA[i]], objB[keysA[i]])) {
      return false
    }
  }

  return true
}

参考

PureComponent

https://segmentfault.com/a/1190000014979065 https://wulv.site/2017-05-31/react-purecomponent.html https://juejin.im/post/5b614d9bf265da0fa759e84b

浅比较 https://www.imweb.io/topic/598973c2c72aa8db35d2e291

展示组件和容器组件 https://juejin.im/post/5a52fe32f265da3e317e008b https://juejin.im/post/5af3d66ef265da0b7b35ec1d

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
性能!!让你的 React 组件跑得再快一点
React 基于虚拟 DOM 和高效 Diff 算法的完美配合,实现了对 DOM 最小粒度的更新。大多数情况下,React 对 DOM 的渲染效率足以我们的业务日常。但在个别复杂业务场景下,性能问题依然会困扰我们。此时需要采取一些措施来提升运行性能,其很重要的一个方向,就是避免不必要的渲染(Render)。
胡哥有话说
2019/12/05
8190
React Hooks 源码解析(1):类组件、函数组件、纯组件
React 源码版本: v16.9.0 源码注释笔记:airingursb/react 1 Class Component VS. Functional Component 根据 React 官网,React 中的组件可分为函数式组件(Functional Component)与类组件(Class Component)。 1.1 Class Component 这是一个我们熟悉的类组件: // Class Componmentclass Welcome extends React.Component {
QQ音乐前端团队
2019/10/21
2.1K0
关于React Hooks和Immutable性能优化的实践,我写了一本掘金小册
上线了不到 5 天,没有任何推文介绍的情况下,销量已经超过 400,这个是我万万没想到的,不过这也侧面反映了各位掘友对我的信任。在后台大概看了一下 ID 名单,其中不乏熟悉的面孔,但更多的是几乎没什么印象甚至完全陌生的 ID,确实,回头看看在掘金这些日子的成长,写作、思考和挣扎的过程是极其痛苦的,但正是因为你偶然看到了文章,不经意点了赞、给了一些反馈,才让我有足够的斗志和毅力坚持下去。可能我们从未谋面,甚至互相连微信都没有,但就偏偏在一个叫"掘金"的地方,我收到了来自一个陌生人的认可,这种感觉从未有过,也是一直激励我不断坚持的动力。各位无论是期待已久还是偶尔打开这篇文章,请让我非常真诚地说上一声: 非常感谢!
winty
2019/12/26
1.5K0
关于React Hooks和Immutable性能优化的实践,我写了一本掘金小册
React源码解析之PureComponet的浅比较
前言: 在 React源码解析之updateClassComponent(下) 中提到了PureComponent的浅比较:
进击的小进进
2020/02/13
5570
「React进阶」探案揭秘六种React‘灵异’现象
今天我们来一期不同寻常的React进阶文章,本文我们通过一些不同寻常的现象,以探案的流程分析原因,找到结果,从而认识React,走进React的世界,揭开React的面纱,我深信,更深的理解,方可更好的使用。
用户6835371
2021/06/01
1.3K0
「React进阶」探案揭秘六种React‘灵异’现象
你真的了解浅比较么?
IMWeb前端团队
2018/01/08
1.6K0
React 组件化开发(一)
写react和传统的js差不多。只是有一个设计思想贯穿了整个框架。用一个公式来表达就是:
一粒小麦
2019/07/18
2.5K0
React 组件化开发(一)
React中的浅比较是如何工作的?
浅比较这个概念在React开发过程中很常见。它在不同的过程中扮演着关键的角色,也可以在React组件生命周期的几个地方找到。判断class组件是否应该更新、React hood的依赖数组、通React.memo 缓存处理等例子
ACK
2022/05/06
3.1K0
React 中,用到的几种浅比较方式及其比较成本科普
开发中的绝大多数时候,我们并不需要关注 React 项目的性能问题。虽然我们在前面几个章节中,也花了几篇文章来分析如何优化 React 的性能体验,但是这些知识点在开发过程中能用到的机会其实比较少。面试的时候用得比较多。
用户6901603
2024/01/17
3710
React 中,用到的几种浅比较方式及其比较成本科普
React Native之组件Component与PureComponent
众所周知,React Native的页面元素是由一个一个的组件所构成的,这些组件包括系统已经提供的组件,如View、TextInput等,还有一些第三方库提供的组件,以及自定义的组件。通常在封装组件的时候都会继承Component,不过在React 15.3版本中系统提供了PureComponent,下面就来看一下这两个组件的区别。
xiangzhihong
2022/11/30
2970
从 0 到 1 实现 React 系列 —— 5.PureComponent 实现 && HOC 探幽
本系列文章在实现一个 cpreact 的同时帮助大家理顺 React 框架的核心内容(JSX/虚拟DOM/组件/生命周期/diff算法/setState/PureComponent/HOC/...) 项目地址
牧云云
2018/09/19
7620
从 0 到 1 实现 React 系列 —— 5.PureComponent 实现 && HOC 探幽
手写一个React-Redux,玩转React的Context API
上一篇文章我们手写了一个Redux,但是单纯的Redux只是一个状态机,是没有UI呈现的,所以一般我们使用的时候都会配合一个UI库,比如在React中使用Redux就会用到React-Redux这个库。这个库的作用是将Redux的状态机和React的UI呈现绑定在一起,当你dispatch action改变state的时候,会自动更新页面。本文还是从它的基本使用入手来自己写一个React-Redux,然后替换官方的NPM库,并保持功能一致。
蒋鹏飞
2020/10/15
3.8K0
手写一个React-Redux,玩转React的Context API
React16中的Component与PureComponent
React中用类的方式声明组件的时候,一般需要继承Component这个类,但是在React16版本中增加了一个PureComponent类,这两个类有什么区别呢?
挥刀北上
2020/02/20
1.3K0
react 学习(13)实现 PureComponent
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解了泪组件内部可以使用 shouldComponentUpdate 返回布尔值进行判断,本小节我们了解下基于该生命周期实现的另一个判断渲染机制的内置组件。
测不准
2022/06/18
3380
react 学习(13)实现 PureComponent
React中的纯组件
React提供了一种基于浅比较模式来确定是否应该重新渲染组件的类React.PureComponent,通常只需要继承React.PureComponent就可以定义一个纯组件。React.PureComponent与React.Component很相似,两者的区别在于React.Component并未实现shouldComponentUpdate(),而React.PureComponent中以浅层对比prop和state的方式来实现了该函数。如果赋予React组件相同的props和state,render()函数会渲染相同的内容,那么在某些情况下使用React.PureComponent可提高性能。
WindRunnerMax
2021/01/18
2.7K0
第二十二篇:思路拓展:如何打造高性能的 React 应用?
React 应用也是前端应用,如果之前你知道一些前端项目普适的性能优化手段,比如资源加载过程中的优化、减少重绘与回流、服务端渲染、启用 CDN 等,那么这些手段对于 React 来说也是同样奏效的。
越陌度阡
2023/08/09
4530
第二十二篇:思路拓展:如何打造高性能的 React 应用?
Web 性能优化: 使用 React.memo() 提高 React 组件性能
React.js 核心团队一直在努力使 React 变得更快,就像燃烧的速度一样。为了让开发者能够加速他们的 React 应用程序,为此增加了很多工具:
前端小智@大迁世界
2019/03/20
5.8K0
Web 性能优化: 使用 React.memo() 提高 React 组件性能
React 渲染性能优化
在React内部已经使用了许多巧妙的技术来最小化由于Dom变更导致UI渲染所耗费的时间。对于很多应用来说,使用React后无需太多工作就会让客户端执行性能有质的提升。然而,还是很其他更多的办法来加速React程序。
随风溜达的向日葵
2018/08/07
1.1K0
React 渲染性能优化
React 16.6新API
其中最重要的是Suspense特性,在之前的React Async Rendering中提到过:
ayqy贾杰
2019/06/12
7950
React 性能优化大挑战:一次理解 Immutable data跟shouldComponentUpdate
作者: TechBridge Weekly/huli https://blog.techbridge.cc/2018/01/05/react-render-optimization/ 前阵子正在重构公司的专案,试了一些东西之后发现自己对于 React 的渲染机制其实不太了解,不太知道 render 什么时候会被触发。而后来我发现不只我这样,其实还有满多人对这整个机制不太熟悉,因此决定写这篇来分享自己的心得。其实不知道怎么优化倒还好,更惨的事情是你自以为在优化,其实却在拖慢效能,而根本的原因就是对 React
企鹅号小编
2018/02/07
8760
相关推荐
性能!!让你的 React 组件跑得再快一点
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验