当前位置: 首页 > 科技观察

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

时间:2023-03-19 16:24:26 科技观察

【.com快速翻译】我们都知道没有人喜欢慢速的Web界面。作为最流行的JavaScript框架之一,React提供了多种提高UI性能的方法。让我们找出来。通常,React通过维护视图的内存模型来工作。这通常称为虚拟DOM,可用于确定何时需要更新实际DOM。然而,由于操作实际DOM的代价很高,我们需要确保仅在必要时更新DOM以提高整体性能。为了从React框架中获得最高的性能,提高React界面的响应效率,本文将从各种功能函数(如Suspense)和基于类的组件出发,讨论十种常用的面向DOM的技术和方法。shouldComponentUpdate在编写基于类的组件时,可以重写shouldComponentUpdate()生命周期方法。该方法的目的是显式声明目标组件是否需要重新渲染。值得注意的是,在更新实际DOM的生命周期中,渲染的开销是非常巨大的。因此,我们只需要让React在组件的props或states发生变化时进行渲染即可。有时您甚至可以跳过渲染以避免整个调用的开销。shouldComponentUpdate的签名和操作都比较简单。在下面的简单示例中,组件需要知道它应该在哪些指定的触发条件下执行更新。此方法将接收到的属性和状态作为参数。如果返回true,则组件会进行渲染,否则不会触发渲染。shouldComponentUpdate(nextProps,nextState){if(this.props.significant!==nextProps.significant){returntrue;}returnfalse;}虽然上面的代码片段主要检查属性,但它也适用于状态。当然,在实际应用中,检查属性或状态并判断是否返回true可能会更复杂。如果你需要比较一些简单的浅值(shallowvalue),那么使用下一个技巧——PureComponent。PureComponent如果你的组件只需要对属性和状态进行简单的浅比较(shallowcomparison,https://stackoverflow.com/a/5703797/467240)来判断是否需要渲染,那么你可以使用类似PureComponent的扩展基类--classMyComponent扩展了React.PureComponent。可以实现:当浅层比较没有发现属性或状态有任何变化时,不会调用render()。顾名思义,PureComponent的意思是:只有当属性或状态发生变化时,才会触发输出的变化,因此组件是纯组件,没有任何副作用。之前的useEffect技巧只适用于那些基于类的组件。要实现与常规功能组件类似的效果,您可以使用功能组件,如useEffecthook和memo。其中useEffect与shouldComponentUpdate的作用类似,允许用户指定:只有当某些变量发生变化时,特定的函数才会生效,从而避免了整体变化的开销。这是一个简单的useEffect示例:constMyComponent=(props)=>{useEffect(()=>{console.info("UpdateComplete:"+props.significantVariable);},[props.significantVariable]);}通过上面的代码从该部分可以看出,如果props.significantVariable发生了变化(即变量发生了变化),那么代码就会运行并生效。用React.memo提供内存作为高阶组件,memo包装了各种组件并扩展了它们的行为能力。也就是说,如果功能组件具有相同的属性,memo可以以缓冲的方式“记住”它们的结果。相应地,可以有效地防止功能组件不管属性是否一致而盲目渲染。为了模仿PureComponent只关注属性的行为,我们可以使用以下代码片段来包装一些功能组件,使它们只检查属性变化,而不检查状态。由于props和state不同,一旦通过比较确定props.quote没有发生变化,则不会重新渲染其对应的组件。constMyComponent=(props)=>{returnprops.quote}exportdefaultReact.memo(SomeComponent)同时React.memo可以通过第二个参数检查函数的等价性:exportdefaultReact.memo(MyComponent,(oldProps,newProps)=>{});通过上面的代码,我们可以比较用例的新旧属性。如果属性相等,则该函数返回true。值得注意的是,这与我们之前介绍的shouldComponentUpdate正好相反,当发现有组件更新时返回true。Windowing(ListVirtualization)现在,让我们将注意力转向一种同时适用于功能组件和类组件的技术——窗口。例如,你有一个数据表或列表,有几千行,如果你想在表对应的应用程序界面上显示大量的数据,就需要以“窗口化”的方式查询数据。换句话说,我们可以通过一次仅加载和显示部分数据来防止大量数据“卡住”应用程序的用户界面(UI)。为此,我们通常可以使用react-window库(参见--https://github.com/bvaughn/react-window)。函数缓存如果您认为函数调用过于昂贵,请考虑缓存它们。如果参数相同,缓存可以返回结果,我们可以使用记忆缓存的方式来避免各种获取数据的调用。当然,函数缓存是否真的适用,还要看函数的具体特性。延迟加载和代码拆分所谓延迟加载是指:我们只在必要时才加载数据。React16.6引入了React.lazy(),允许用户按需拆分代码。这意味着您在使用常规组件语法的同时获得了延迟加载的所有语义。当然,React16.6之前的版本也不是不能实现代码拆分,只是在处理大代码库的时候比较麻烦。并发模式、Suspense和useDeferredValue是React16最引人注目的新特性。并发模式允许用户使用Suspense组件来实现数据获取和渲染的并行处理,从而大大提高应用程序的实际感知性能。除了可以使用Suspense组件来定义数据获取区域,我们还可以使用React16带来的useDeferredValue等新组件来改进auto-suggest的工作方式,从而避免用户遇到Sexualtyping等错误和其他糟糕的经历。数据获取的Debounce和throttle在大多数情况下,我们可以使用debounce或throttle功能来更好的处理React的并发模式。如果你的代码库锁定在老版本的渲染引擎上,无法开启并发模式,这样的功能可以有效避免数据获取过程中的混乱。例如,如果您希望在用户键入数据时实时获取他们的输入,则整体性能将受到显着影响,因为每次击键都会触发请求。对此,我们可以使用debounce或throttle功能来缓解此类问题。Profiling除了上面提到的技术,我们还可以分析应用的性能,了解性能瓶颈在哪里,验证上述改进方法的实际效果。目前,Chrome和Firefox等浏览器都带有内置分析器。启用React的开发模式后,您将能够分析正在使用的某些组件。这对于检查网络状态和识别后端调用中的延迟很有用。基于此,你可以明确判断是前端JavaScript代码问题,还是后端需要修复的缺陷。此外,React16.5及更高版本还提供了一个名为DevToolsProfiler的工具(https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html)。它不仅可以在并发模式下为每个功能提供更详细的服务功能和集成,还可以通过多种方式对应用程序的行为进行切片和切块。另一类Profiler组件可以显示组件渲染生命周期中的各种细节。React的生产构建最后,在部署到生产时,您还需要确保生产构建是精简的,并且在开发和调试期间不包含任何日志记录。当然,具体步骤取决于您使用的构建工具。如果您使用的是CreateReactApp,请参考--https://create-react-app.dev/docs/production-build/。原标题:调优ReactUI性能的10个技巧,作者:MatthewTyson