提高React界面性能的十个技巧

总的说来,React是通过维护视图中的内存(in-memory)模型来运作的。这通常被称为虚拟DOM,它可以被用来确定实际DOM何时需要被更新。不过,由于操控实际DOM的成本较高,因此我们需要确保仅在必要时才去更新DOM,进而提高整体性能。

为了从React框架中获取最高性能,并提升React界面的响应效率,本文将从各种功能函数(如Suspense)、以及基于类的组件出发,和您讨论十项常用的、面向DOM的技术与方法。

shouldComponentUpdate

在编写基于类的组件时,您可以重写shouldComponentUpdate()的生命周期方法。该方法的目的在于:明确地声明目标组件是否需要被重新渲染(re-rendering)。值得注意的是,在更新实际DOM的生命周期中,渲染的开销是非常巨大的。因此,只有在组件的属性(props)或状态(states)发生变化时,我们才需要让React执行渲染。有时您甚至可以跳过渲染,以避免整体调用所产生的开销。

shouldComponentUpdate的签名和操作比较简单。在如下简单示例中,组件需要知晓应该在何种指定触发条件下,去执行更新。该方法将接收到的属性与状态当作参数,如果返回为true,组件将执行渲染,否则并不触发渲染。

shouldComponentUpdate(nextProps, nextState) { 
    if (this.props.significant !== nextProps.significant) { 
      return true; 
    } 
    return false; 
  } 

虽然上述代码段主要检查的是属性,但是它对于状态也同样适用。当然,在实际应用中,对于属性或状态的检查,并判定是否返回true,可能会更加复杂。如果您需要比较某个简单的浅层值(shallow value),那么请使用下一个技巧--PureComponent。

PureComponent

如果您的组件仅需要对属性和状态进行简单的浅层比较(shallow comparison,https://stackoverflow.com/a/5703797/467240),以确定是否需要渲染,那么完全可以使用PureComponent之类的扩展基类--class MyComponent extends React.PureComponent。它可以实现:当通过浅层比较,并未发现属性或状态发生了任何变化时,render()就不会被调用。顾名思义,PureComponent表示:仅在属性或状态改变时,才会触发输出的更改,因此该组件是纯净的,不会带有任何副作用。

useEffect

前面的技巧仅适用于那些基于类的组件。为了达到与常规功能性组件相似的效果,您可以使用useEffect hook和memo之类的功能性组件。其中,useEffect与shouldComponentUpdate有着相似的效果,它允许用户指定:仅在某些变量发生更改的情况下,生效某种特定的功能,从而避免了整体变更的开销。下面是一个简单的useEffect示例:

const MyComponent = (props) => { 
  useEffect(() => { 
    console.info("Update Complete: " + props.significantVariable); 
  }, [props.significantVariable]); 
} 

由上述代码段可知,如果props.significantVariable已被更改(即变量发生了变化),那么该代码就会运行生效。

用React.memo提供记忆

作为一个高阶组件,memo包装了各种组件,并扩展了它们的行为能力。也就是说,如果功能性组件具有相同的属性,memo便能够以缓冲的方式,“记住”它们的结果。据此,它可以有效地防止功能性组件在无视属性是否一致的情况下,去盲目地执行渲染。

为了模仿PureComponent只关注属性的行为,我们可以使用如下代码段来包装某些功能性组件,使其只检查属性的更改,而非状态。由于属性和状态是不同的,因此通过比较,一旦props.quote被认定为未发生改变,则其对应的组件也不会重新渲染。

const MyComponent = (props) => { 
  return <span>props.quote</span> 
} 
export default React.memo(SomeComponent) 

同时,React.memo 可以通过第二个参数,来检查函数的等效性:

export default React.memo(MyComponent, (oldProps, newProps) => {} ); 

通过上述代码,我们可以实现对用例新的和旧的属性进行比较。如果属性相等,该函数则返回true。值得注意的是,这与我们在前面介绍的shouldComponentUpdate,在发现组件出现更新时返回true,正好相反。

窗口化(列表虚拟化)

现在,让我们将注意力转移到一项同时适用于功能性和类组件的技术--窗口化(windowing)上。例如有一个具有数千行记录的数据表或列表,如果您想在该表所对应的应用界面上显示大量数据集,那么就需要采用“窗口化”的方式来查询数据。也就是说,我们可以通过一次性仅加载和显示部分数据的形式,防止大量数据“卡死”应用的用户界面(UI)。为此,我们时常可以用到react-window库(请参见--https://github.com/bvaughn/react-window)。

函数缓存

如果您觉得函数调用的成本过高,那么可以考虑对其进行缓存。如果各个参数相同,而且缓存能够返回结果,我们就可以使用存储式缓存(memorized cache)的方式,来避免各种针对数据获取的调用。当然,函数缓存是否真的适用,还取决于函数的具体特征。

延迟加载和代码拆分

所谓延迟加载是指:我们仅在必要时,才去加载数据。React 16.6引入了React.lazy(),它允许用户对代码按需进行拆分。这意味着,您可以在使用常规组件语法的同时,获得各种延迟加载的语义。

当然,React 16.6之前的版本,并非无法实现代码拆分,只是在处置大型代码库时,相对比较繁琐。

并发模式、Suspense和useDeferredValue

作为React 16的一项最显著的新功能,并发模式可以让用户通过使用Suspense组件,实现数据获取和渲染的并行处理,进而极大地提高应用程序的实际感知性能。

我们除了能够用Suspense组件来定义数据的获取区域之外,还可以使用诸如useDeferredValue等由React 16带来的新组件,来提升自动建议(auto-suggest)等工作方式,进而避免用户碰到诸如错误性的键入等不良的体验。

数据获取的防抖(Debounce)和限流(throttle)

大多数情况下,我们可以通过debounce或throttle函数,来更好地处理React的并发模式。如果您的代码库被锁定为旧版的渲染引擎,而无法开启并发模式时,此类函数便可以有效地避免在数据获取的过程中,出现混乱的局面。

例如,如果您想在用户键入数据的同时,实时地获取他们的输入,那么由于每个击键都会触发一个请求,因此整体的性能会大打折扣。对此,我们便可以使用debounce或throttle函数,来缓解此类问题。

分析(Profiling)

除了上面提到的技术,我们还可以通过对应用程序进行性能分析,来获悉性能瓶颈的所在,并验证上述改进方法的实际效果。目前,像Chrome和Firefox之类的浏览器,都带有内置的分析器(profiler)。一旦启用了React的开发模式(dev mode),您将可以通过分析器,来查看某些正在使用的特定组件。这对于检查网络的状态,以及识别后端调用的延迟,都是非常实用的。据此,您可以清晰地判断出,到底是前端JavaScript的代码问题,还是存在着需要后端修复的缺陷。

此外,React 16.5以及更高的版本,还提供了一个名为DevTools Profiler(https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html)的工具。它既能够为处于并发模式的各个函数,提供了更加详尽的服务功能与集成;又可以通过多种方法,对应用程序的行为活动进行切片(slice)和切块(dice)。

另一类Profiler组件则能够展现组件渲染生命周期中的各种详细信息。

React的生产环境构建

最后,在部署生产环境时,您还需要确保生产环境构建(production build)的精简性、且不包含任何开发调试过程中的日志记录。当然,具体步骤取决于您所使用的构建工具。

以上就是提高React界面性能的十个技巧的详细内容,更多关于提高React界面性能的资料请关注我们其它相关文章!

(0)

相关推荐

  • React函数式组件的性能优化思路详解

    优化思路 主要优化的方向有2个: 减少重新 render 的次数.因为在 React 里最重(花时间最长)的一块就是 reconction(简单的可以理解为 diff),如果不 render,就不会 reconction. 减少计算的量.主要是减少重复计算,对于函数式组件来说,每次 render 都会重新从头开始执行函数调用. 在使用类组件的时候,使用的 React 优化 API 主要是:shouldComponentUpdate和 PureComponent 那么在函数式组件中,我们怎么做性能

  • React性能优化系列之减少props改变的实现方法

    React性能优化的一个核心点就是减少render的次数.如果你的组件没有做过特殊的处理(SCU -- shouldComponentUpdate或使用PureComponent),那每次父组件render时,子组件就会跟着一起被重新渲染.通常一个复杂的子组件都会进行一些优化,比如:SCU 使用PureComponent组件.对于SCU基本上进行的也都是浅比较,深比较的代价太高. 对于这些被优化的子组件,我们要减少一些不必要的props改变:比如事件绑定.对于那些依赖于配置项的组件,我们更是减少

  • 详解使用React.memo()来优化函数组件的性能

    React核心开发团队一直都努力地让React变得更快.在React中可以用来优化组件性能的方法大概有以下几种: 组件懒加载(React.lazy(...)和<Suspense />) Pure Component shouldComponentUpdate(...){...}生命周期函数 本文还会介绍React16.6加入的另外一个专门用来优化函数组件(Functional Component)性能的方法: React.memo. 无用的渲染 组件是构成React视图的一个基本单元.有些组件

  • 浅谈React组件之性能优化

    高德纳: "我们应该忘记忽略很小的性能优化,可以说97%的情况下,过早的优化是万恶之源,而我们应该关心对性能影响最关键的另外3%的代码." 不要将性能优化的精力浪费在对整体性能提高不大的代码上,而对性能有关键影响的部分,优化并不嫌早.因为,对性能影响最关键的部分,往往涉及解决方案核心,决定整体的架构,将来要改变的时候牵扯更大. 1. 单个React组件的性能优化 React利用Virtual DOM来提升渲染性能,虽然每一次页面更新都是最组件的从新渲染,但是并不是将之前的渲染内容全部抛

  • 浅谈react性能优化的方法

    React性能优化思路 软件的性能优化思路就像生活中去看病,大致是这样的: 使用工具来分析性能瓶颈(找病根) 尝试使用优化技巧解决这些问题(服药) 使用工具测试性能是否确实有提升(疗效确认) 初识react只是为了尽快完成项目,后期进行代码审查时候发现有很多地方需要优化,因此做了个小结. Code Splitting shouldComponentUpdate避免重复渲染 使用不可突变数据结构 组件尽可能的进行拆分.解耦 列表类组件优化 bind函数优化 不要滥用props ReactDOMSe

  • react性能优化达到最大化的方法 immutable.js使用的必要性

    一行代码胜过千言万语.这篇文章呢,主要讲述我一步一步优化react性能的过程,为什么要用immutable.js呢.毫不夸张的说.有了immutable.js(当然也有其他实现库)..才能将react的性能发挥到极致!要是各位看官用过一段时间的react,而没有用immutable那么本文非常适合你.那么我开始吧! 1.对于react的来说,如果父组件有多个子组件 想象一下这种场景,一个父组件下面一大堆子组件.然后呢,这个父组件re-render.是不是下面的子组件都得跟着re-render.可

  • 提高React界面性能的十个技巧

    总的说来,React是通过维护视图中的内存(in-memory)模型来运作的.这通常被称为虚拟DOM,它可以被用来确定实际DOM何时需要被更新.不过,由于操控实际DOM的成本较高,因此我们需要确保仅在必要时才去更新DOM,进而提高整体性能. 为了从React框架中获取最高性能,并提升React界面的响应效率,本文将从各种功能函数(如Suspense).以及基于类的组件出发,和您讨论十项常用的.面向DOM的技术与方法. shouldComponentUpdate 在编写基于类的组件时,您可以重写s

  • 提高Node.js性能的应用技巧分享

    一.实现一个反向代理服务器 相比大多数应用服务器,Node.js 可以很轻松的处理大量的网络流量,但这并不是 Node.js 的设计初衷. 如果你有一个高流量的站点,提高性能的第一步是在你的 Node.js 前面放一个反向代理服务器.这可以保护你的 Node.js 服务器免于直接暴露在网络中,而且可以允许你灵活的使用多个应用服务器做负载均衡和静态文件缓存. 使用 NGINX 在一个已经存在的服务器前做反向代理,作为 NGINX 的一个核心应用,已经被用于全世界成千上万的站点中. 下面是使用 NG

  • 提高jQuery性能优化的技巧

    下面把提高jQuery性能优化技巧给大家分享如下: 缓存变量 DOM遍历是昂贵的,所以尽量将会重用的元素缓存. 复制代码 代码如下: // 糟糕 h = $('#element').height(); $('#element').css('height',h-20); // 建议 $element = $('#element'); h = $element.height(); $element.css('height',h-20); 避免全局变量 jQuery与javascript一样,一般来说

  • 使用Function.apply()的参数数组化来提高 JavaScript程序性能的技巧

    我们再来聊聊Function.apply() 在提升程序性能方面的技巧. 我们先从 Math.max() 函数说起, Math.max后面可以接任意个参数,最后返回所有参数中的最大值. 比如 alert(Math.max(5,8)) //8 alert(Math.max(5,7,9,3,1,6)) //9 但是在很多情况下,我们需要找出数组中最大的元素. var arr=[5,7,9,1] alert(Math.max(arr)) // 这样却是不行的.一定要这样写 function getMa

  • 分享五个PHP7性能优化提升技巧

    PHP7已经发布了, 作为PHP10年来最大的版本升级, 最大的性能升级, PHP7在多放的测试中都表现出很明显的性能提升, 然而, 为了让它能发挥出最大的性能, 我还是有几件事想提醒下. 1. Opcache 记得启用Zend Opcache, 因为PHP7即使不启用Opcache速度也比PHP-5.6启用了Opcache快, 所以之前测试时期就发生了有人一直没有启用Opcache的事情. 启用Opcache非常简单, 在php.ini配置文件中加入: zend_extension=opcac

  • 提高 DHTML 页面性能

    摘要:本文说明了某些 DHTML 功能对性能的重大影响,并提供了一些提高 DHTML 页面性能的技巧. 目录 简介 成批处理 DHTML 更改 使用 innerText 使用 DOM 添加单个元素 扩展 SELECT 元素中的选项 用 DOM 更新表 编写一次,使用多次 请勿过多使用动态属性 数据绑定很有效 不要在 document 对象中设置 expando 属性 避免切换类和样式规则 查找父项之前,先折叠文本范围 其他资料 简介 动态 HTML (DHTML) 在 Microsoft® In

  • 十分简单易懂的Java应用程序性能调优技巧分享

    大多数开发人员理所当然地以为性能优化很复杂,需要大量的经验和知识.好吧,不能说这是完全错误的.优化应用程序以获得最佳性能不是一件容易的事情.但是,这并不意味着如果你不具备这些知识,就不能做任何事情.这里有11个易于遵循的建议和最佳实践可以帮助你创建一个性能良好的应用程序. 大部分建议是针对Java的.但也有若干建议是与语言无关的,可以应用于所有应用程序和编程语言.在讨论专门针对Java的性能调优技巧之前,让我们先来看看通用技巧. 1.在你知道必要之前不要优化 这可能是最重要的性能调整技巧之一.你

  • python一些性能分析的技巧

    当我们开始精通编程语言时,我们不仅希望实现最终目标,而且希望使我们的程序高效. 在这个教程中,我们将学习一些Ipython的命令,这些命令可以帮助我们对Python代码进行时间分析. 注意,在本教程中,我建议使用Anaconda. 1.分析一行代码 要检查一行python代码的执行时间,请使用 %timeit .下面是一个简单的例子来了解它的工作原理: #### magics命令%timeit的简单用法 %timeit [num for num in range(20)] #### 输出 1.0

  • 分享12个Vue开发中的性能优化小技巧(实用!)

    目录 前言 1.长列表性能优化 1.不做响应式 2.虚拟滚动 2.v-for遍历避免同时使用v-if 3.列表使用唯一key 4.使用v-show复用DOM 5.无状态的组件用函数式组件 6.子组件分割 7.变量本地化 8.第三方插件按需引入 9.路由懒加载 10.keep-alive缓存页面 11.事件的销毁 12.图片懒加载 总结 前言 性能优化,是每一个开发者都会遇到的问题,特别是现在越来越重视体验,以及竞争越来越激烈的环境下,对于我们开发者来说,只完成迭代,把功能做好是远远不够的,最重要

  • .NET使用结构体替代类提升性能优化的技巧

    目录 前言 现实的案例 内存占用 计算速度 总结 附录 前言 我们知道在C#和Java明显的一个区别就是C#可以自定义值类型,也就是今天的主角struct,我们有了更加方便的class为什么微软还加入了struct呢?这其实就是今天要谈到的一个优化性能的Tips使用结构体替代类.那么使用结构体替代类有什么好处呢?在什么样的场景需要使用结构体来替代类呢?今天的文章为大家一一解答.注意:本文全部都以x64位平台为例 现实的案例 举一个现实系统的例子,大家都知道机票购票的流程,开始选择起抵城市和机场(

随机推荐