www.2527.com_澳门新葡8455手机版_新京葡娱乐场网址_
做最好的网站

种优化技术,详解使用React

2020-01-18 06:54 来源:未知

时间: 2019-09-07阅读: 224标签: 优化

React核心开发团队一直都努力地让React变得更快。在React中可以用来优化组件性能的方法大概有以下几种:

React性能优化思路

谷歌的数据表明,一个有 10 条数据 0.4 秒可以加载完的页面,在变成 30 条数据加载时间为 0.9 秒后,流量和广告收入减少了 20%。当谷歌地图的首页文件大小从 100kb 减少到 70~80kb 时,流量在第一周涨了 10%,接下来的三周涨了 25%。

组件懒加载和) Pure Component shouldComponentUpdate{...}生命周期函数

软件的性能优化思路就像生活中去看病,大致是这样的:

腾讯的前端工程师根据长期的数据监控也发现页面的一秒钟延迟会造成 9.4% 的 PV 的下降,8.3% 跳出率的增加以及 3.5% 转化率的下降。

本文还会介绍React16.6加入的另外一个专门用来优化函数组件性能的方法: React.memo。

使用工具来分析性能瓶颈

可以看出,性能优化商业上来说很重要。

无用的渲染

尝试使用优化技巧解决这些问题

但是,更重要的还是屏幕前我们的用户,让用户在使用产品时有更快更舒适的浏览体验,这算是一种前端工程师的自我修养。

组件是构成React视图的一个基本单元。有些组件会有自己本地的状态, 当它们的值由于用户的操作而发生改变时,组件就会重新渲染。在一个React应用中,一个组件可能会被频繁地进行渲染。这些渲染虽然有一小部分是必须的,不过大多数都是无用的,它们的存在会大大降低我们应用的性能。

使用工具测试性能是否确实有提升

所以今天就分享一下如何去优化我们的 React 项目,进而提升用户体验。

import React from 'react';class TestC extends React.Component { constructor; this.state = { count: 0 } } componentWillUpdate { console.log('componentWillUpdate') } componentDidUpdate { console.log } render() { return (  {this.state.count} this.setState}>Click Me  ); }}export default TestC;

初识react只是为了尽快完成项目,后期进行代码审查时候发现有很多地方需要优化,因此做了个小结。

1使用React.Fragment 来避免向 DOM 添加额外的节点

TestC组件有一个本地状态count,它的初始值是0。当我们点击Click Me按钮时,count的值被设置为1。这时候屏幕的数字将会由0变成1。当我们再次点击该按钮时,count的值还是1, 这时候TestC组件不应该被重新渲染,可是现实是这样的吗?

Code Splitting shouldComponentUpdate避免重复渲染 使用不可突变数据结构 组件尽可能的进行拆分、解耦 列表类组件优化 bind函数优化 不要滥用props ReactDOMServer进行服务端渲染组件

我们在写 React 代码时,会经常遇到返回一组元素的情况,代码像这样:

为了测试count重复设置相同的值组件会不会被重新渲染, 我为TestC组件添加了两个生命周期函数: componentWillUpdate和componentDidUpdate。componentWillUpdate方法在组件将要被重新渲染时被调用,而componentDidUpdate方法会在组件成功重渲染后被调用。

Code Splitting

class Parent extends React.Component { render() { return ( h1Hello there!/h1 h1Hello there again!/h1 ) }}

在浏览器中运行我们的代码,然后多次点击Click Me按钮,你可以看到以下输出:

Code Splitting 可以帮你“懒加载”代码,如果你没办法直接减少应用的体积,那么不妨尝试把应用从单个 bundle 拆分成单个 bundle 多份动态代码的形式。

如果我们写成这样,控制台会报错误:JSX parent expressions must have,告诉我们只能返回一个元素,所以我们通常会在最外层包裹一个 div 元素,如下所示:

我们可以看到'componentWillUpdate'和'componentWillUpdate'在每次我们点击完按钮后,都会在控制台输出来。所以即使count被设置相同的值,TestC组件还是会被重新渲染,这些就是所谓的无用渲染。

webpack提供三种代码分离方法,详情见webpack官网

class Parent extends React.Component { render() { return ( div h1Hello there!/h1 h1Hello there again!/h1 /div ) }}

Pure Component/shouldComponentUpdate

入口起点:使用 entry 配置手动地分离代码。 防止重复:使用 SplitChunks 去重和分离 chunk。 动态导入:通过模块的内联函数调用来分离代码。

这样做虽然能正常执行,但是会额外创建不必要的DOM节点,这可能会导致创建许多无用的元素,并且在我们的渲染数据来自特定顺序的子组件时,某些情况下也会生成许多无效的节点。请考虑以下代码:

为了避免React组件的无用渲染,我们可以实现自己的shouldComponentUpdate生命周期函数。

在此,主要了解一下第三种动态导入的方法。

class Table extends React.Component { render() { return ( table tr Columns / /tr /table ); }}class Columns extends React.Component { render() { return ( div tdcolumn one/td tdcolumn two/td /div ); }}

当React想要渲染一个组件的时候,它将会调用这个组件的shouldComponentUpdate函数, 这个函数会告诉它是不是真的要渲染这个组件。

1、例如可以把下面的import方式

上面的代码将在我们的组件中呈现以下内容:

如果我们的shouldComponentUpdate函数这样写:

import { add } from './math';console.log;
table tr div tdcolumn one/td tdcolumn two/td /div /tr/table
shouldComponentUpdate { return true }

改写成动态 import 的形式,让首次加载时不去加载 math 模块,从而减少首次加载资源的体积。

这显然不是我们想看到的,React 为我们提供了Fragments,Fragments允许我们将子列表分组,而无需向 DOM 添加额外节点。我们可以将组件重新编写为:

其中各个参数的含义是:

import.then(math => { console.log;
class Columns extends React.Component { render() { return ( React.Fragment tdcolumn one/td tdcolumn two/td /React.Fragment ); }}

nextProps: 组件将会接收的下一个参数props nextProps: 组件的下一个状态state

2、例如引用react的高阶组件react-loadable进行动态import。

2使用React.Lazy 延迟加载组件

因为我们的shouldComponentUpdate函数一直返回true,这就告诉React,无论何种情况都要重新渲染该组件。

import Loadable from 'react-loadable';import Loading from './loading-component';const LoadableComponent = Loadable => import, loading: Loading,});export default class App extends React.Component { render() { return ; }}

有时我们只想在请求时加载部分组件,例如,仅在单击购物车图标时加载购物车数据,在用户滚动到该点时在长图像列表的底部加载图像等。

shouldComponentUpdate { return false}

上面的代码在首次加载时,会先展示一个 loading-component,然后动态加载 my-component 的代码,组件代码加载完毕之后,便会替换掉 loading-component

React.Lazy 帮助我们按需加载组件,从而减少我们应用程序的加载时间,因为只加载我们所需的组件。

因为这个方法的返回值是false,所以React永远都不会重新渲染我们的组件。

shouldComponentUpdate避免重复渲染

React.lazy接受一个函数,这个函数需要动态调用import()。它必须返回一个 Promise,该 Promise 需要 resolve 一个 defalut export 的 React 组件。如下所示:

因此当你想要React重新渲染你的组件的时候,就在这个方法中返回true,否则返回false。现在让我们用shouldComponentUpdate重写之前的TestC组件:

当一个组件的props或者state改变时,React通过比较新返回的元素和之前渲染的元素来决定是否有必要更新实际的DOM。当他们不相等时,React会更新DOM。

class MyComponent extends Component{ render() { return (divMyComponent/div) }}const MyComponent = React.lazy(()=import('./MyComponent.js'))function App() { return (divMyComponent //div)}
import React from 'react';class TestC extends React.Component { constructor; this.state = { count: 0 } } componentWillUpdate { console.log('componentWillUpdate') } componentDidUpdate { console.log } shouldComponentUpdate { if (this.state.count === nextState.count) { return false } return true } render() { return (  { this.state.count }  this.setState }> Click Me   ); }}export default TestC;

在一些情况下,你的组件可以通过重写这个生命周期函数shouldComponentUpdate来提升速度, 它是在重新渲染过程开始前触发的。 这个函数默认返回true,可使React执行更新。

在编译时,使用Webpack 解析到该语法时,它会自动地开始进行代码分割。最终,我们的应用程序将会被分成含有多个 UI 片段的包,这些 UI 片段将在需要时加载,如果你使用 Create React App,该功能已配置好,你能立刻使用这个特性。Next.js也已支持该特性而无需再配置。

我们在TestC组件里添加了shouldComponentUpdate方法,判断如果现在状态的count和下一个状态的count一样时,我们返回false,这样React将不会进行组件的重新渲染,反之,如果它们两个的值不一样,就返回true,这样组件将会重新进行渲染。

为了进一步说明问题,引用官网的图解释一下,如下图( SCU表示shouldComponentUpdate,绿色表示返回true,红色表示返回false;vDOMEq表示虚拟DOM比对,绿色表示一致):

3使用React.Suspense

再次在浏览器中测试我们的组件,刚开始的界面是这样的:

根据渲染流程,首先会判断shouldComponentUpdate是否需要更新。如果需要更新,则调用组件的render生成新的虚拟DOM,然后再与旧的虚拟DOM对比,如果对比一致就不更新,如果对比不同,则根据最小粒度改变去更新DOM;如果SCU不需要更新,则直接保持不变,同时其子元素也保持不变。

在交换组件时,会出现一个小的时间延迟,例如在 MyComponent 组件渲染完成后,包含 OtherComponent 的模块还没有被加载完成,这可能就会出现白屏的情况,我们可以使用加载指示器为此组件做优雅降级,这里我们使用 Suspense 组件来解决。

这时候,就算我们多次点击Click Me按钮,也只能看到两行输出:

C1根节点,绿色SCU、红色vDOMEq,表示需要更新。 C2节点,红色SCU,表示不需要更新,同时 C4、C5作为其子节点也不需要检查更新。 C3节点,绿色SCU、红色vDOMEq,表示需要更新。 C6节点,绿色SCU、红色vDOMEq,表示需要更新。 C7节点,红色SCU,表示不需要更新。 C8节点,绿色SCU,表示React需要渲染这个组件;绿色vDOMEq,表示虚拟DOM一致,不更新DOM。

React.Suspense用于包装延迟组件以在加载组件时显示后备内容。

componentWillUpdatecomponentDidUpdate

因此,我们可以通过根据自己的业务特性,重载shouldComponentUpdate,只在确认真实DOM需要改变时,再返回true。一般的做法是比较组件的props和state是否真的发生变化,如果发生变化则返回true,否则返回false。引用官网的案例。

// MyComponent.jsconst Mycomponent = React.lazy(()=import('./component.js'))function App() { return ( div Suspense fallback={divloading ../div} MyComponent / /Suspense /div)}

因为第二次点击Click Me按钮后count值一直是1,这样shouldComponentUpdate一直返回false,所以组件就不再被重新渲染了。

class CounterButton extends React.Component { constructor; this.state = {count: 1}; } shouldComponentUpdate { if (this.props.color !== nextProps.color) { return true; } if (this.state.count !== nextState.count) { return true; } return false; } render() { return (  this.setState(state => ({count: state.count   1}))}> Count: {this.state.count}  ); }}

上面的代码中,fallback属性接受任何在组件加载过程中你想展示的 React 元素。

那么如何验证后面state的值发生改变,组件还是会被重新渲染呢?我们可以在浏览器的React DevTools插件中直接对TestC组件的状态进行更改。具体做法是, 在Chrome调试工具中点击React标签,在界面左边选中TestC组件,在界面的右边就可以看到其状态state中只有一个键count,且其值是1:

在以上代码中,shouldComponentUpdate只检查props.color和state.count的变化。如果这些值没有变化,组件就不会更新。当你的组件变得更加复杂时,你可以使用类似的模式来做一个“浅比较”,用来比较属性和值以判定是否需要更新组件。这种模式十分常见,因此React提供了一个辅助对象来实现这个逻辑

你可以将Suspense组件置于懒加载组件之上的任何位置,你甚至可以用一个Suspense组件包裹多个懒加载组件。

然后让我们点击count的值1,将其修改为2,然后按回车键:

  • 继承自React.PureComponent。
const OtherComponent = React.lazy(() = import('./OtherComponent'));const AnotherComponent = React.lazy(() = import('./AnotherComponent'));function MyComponent() { return ( div Suspense fallback={divLoading.../div} section OtherComponent / AnotherComponent / /section /Suspense /div );}

你将会看到控制台有以下输出:

大部分情况下,你可以使用React.PureComponent而不必写你自己的shouldComponentUpdate,它只做一个浅比较。但是当你比较的目标为引用类型数据,浅比较会忽略属性或状态突变的情况,此时你不能使用它,此时你需要关注下面的不可突变数据。

5使用 shouldComponentUpdate() 防止不必要的重新渲染

componentWillUpdatecomponentDidUpdatecomponentWillUpdatecomponentDidUpdate

附:数据突变是指变量的引用没有改变,但是引用指向的数据发生了变化。例如const x = {foo:'foo'}。x.foo='none' 就是一个突变。

当一个组件的props或state变更,React 会将最新返回的元素与之前渲染的元素进行对比,以此决定是否有必要更新真实的 DOM,当它们不相同时 React 会更新该 DOM。

state的count被改变了,组件也被重新渲染了。

使用不可突变数据结构

即使 React 只更新改变了的 DOM 节点,重新渲染仍然花费了一些时间。在大部分情况下它并不是问题,但是如果渲染的组件非常多时,就会浮现性能上的问题,我们可以通过覆盖生命周期方法shouldComponentUpdate来进行提速。

现在让我们使用另外一种方法PureComponent来对组件进行优化。

引用官网中的例子解释一下突变数据产生的问题。例如,假设你想要一个ListOfWords组件来渲染一个逗号分隔的单词列表,并使用一个带了点击按钮名字叫WordAdder的父组件来给子列表添加一个单词。以下代码并不正确:

shouldComponentUpdate方法会在重新渲染前被触发。其默认实现总是返回true,如果组件不需要更新,可以在shouldComponentUpdate中返回false来跳过整个渲染过程。其包括该组件的render调用以及之后的操作。

React在v15.5的时候引入了Pure Component组件。React在进行组件更新时,如果发现这个组件是一个PureComponent,它会将组件现在的state和props和其下一个state和props进行浅比较,如果它们的值没有变化,就不会进行更新。要想让你的组件成为Pure Component,只需要extends React.PureComponent即可。

class ListOfWords extends React.PureComponent { render() { return {this.props.words.join}; }}class WordAdder extends React.Component { constructor; this.state = { words: ['marklar'] }; this.handleClick = this.handleClick.bind; } handleClick() { // 这段内容将会导致代码不会按照你预期的结果运行 const words = this.state.words; words.push; this.setState; } render() { return (     ); }}
shouldComponentUpdate(nextProps, nextState) { return nextProps.next !== this.props.next }

让我们用PureComponent去改写一下我们的代码吧:

导致代码无法正常工作的原因是 PureComponent 仅仅对 this.props.words的新旧值进行“浅比较”。在words值在handleClick中被修改之后,即使有新的单词被添加到数组中,但是this.props.words的新旧值在进行比较时是一样的,因此 ListOfWords 一直不会发生渲染。避免此类问题最简单的方式是避免使用值可能会突变的属性或状态,如:

6使用React.PureComponent

import React from 'react';class TestC extends React.PureComponent { constructor; this.state = { count: 0 } } componentWillUpdate { console.log('componentWillUpdate') } componentDidUpdate { console.log } /*shouldComponentUpdate { if (this.state.count === nextState.count) { return false } return true }*/ render() { return (  { this.state.count }  this.setState }> Click Me   ); }}export default TestC;

1、数组使用concat,对象使用Object.assign()

React.PureComponent与 React.Component 很相似。两者的区别在于 React.Component并未实现 shouldComponentUpdate(),而 React.PureComponent 中以浅层对比 prop 和 state 的方式来实现了该函数。

在上面的代码中,我将shouldComponentUpdate的代码注释掉了,因为React.PureComponent本身就帮我们实现了一样的功能。

handleClick() { this.setState(prevState => ({ words: prevState.words.concat;}

// 假设我们有一个叫colormap的对象,下面方法不污染原始对象function updateColorMap { return Object.assign({}, colormap, {right: 'blue'});}

如果赋予 React 组件相同的 props 和 state,render()函数会渲染相同的内容,那么在某些情况下使用React.PureComponent可提高性能。

改完代码后,我们刷新一下浏览器,然后多次点击Click Me按钮看组件被渲染了多少遍:

2、ES6支持数组或对象的spread语法

// 使用 React.PureComponentclass MyComponent extends React.PureComponent { render() { return (divMyComponent/div) }}class MyComponent extends React.Component { render() { return (divMyComponent/div) }}

由上面的输出可知,我们的component只在state由0变为1时被重新渲染了,后面都没有进行渲染。

handleClick() { this.setState(prevState => ({ words: [...prevState.words, 'marklar'], }));};

function updateColorMap { return {...colormap, right: 'blue'};}

React.PureComponent 中的 shouldComponentUpdate()仅作对象的浅层比较。如果对象中包含复杂的数据结构,则有可能因为无法检查深层的差别,产生错误的比对结果。仅在你的 props 和 state 较为简单时,才使用 React.PureComponent,或者在深层数据结构发生变化时调用 forceUpdate()来确保组件被正确地更新。你也可以考虑使用 immutable 对象加速嵌套数据的比较。

函数组件

3、使用不可突变数据immutable.js

7使用 React.memo 来缓存组件

上面我们探讨了如何使用PureComponentshouldComponentUpdate的方法优化类组件的性能。虽然类组件是React应用的主要组成部分,不过函数组件同样可以被作为React组件使用。

immutable.js使得变化跟踪很方便。每个变化都会导致产生一个新的对象,因此我们只需检查索引对象是否改变。

React.memo使用了缓存,缓存技术用于通过存储昂贵的函数调用的结果来加速程序,并在再次发生相同的输入时返回缓存的结果。

function TestC { return (  I am a functional component  )}
const SomeRecord = Immutable.Record;const x = new SomeRecord;const y = x.set;x === y; // false

如果你的函数组件在给定相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在React.memo中调用,以此通过记忆组件渲染结果的方式来提高组件的性能表现。这意味着在这种情况下,React 将跳过渲染组件的操作并直接复用最近一次渲染的结果。默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现。

对于函数组件,它们没有诸如state的东西去保存它们本地的状态(虽然在React Hooks中函数组件可以使用useState去使用状态), 所以我们不能像在类组件中使用shouldComponentUpdate等生命函数去控制函数组件的重渲染。当然,我们也不能使用extends React.PureComponent了,因为它压根就不是一个类。

在这个例子中,x突变后返回了一个新的索引,因此我们可以安全的确认x被改变了。

const MyComponent = ({user}) ={ const {name, occupation} = user; return ( div h4{name}/h4 p{occupation}/p /div )}// 比较函数function areEqual(prevProps, nextProps) { /* 如果把 nextProps 传入 render 方法的返回结果与 将 prevProps 传入 render 方法的返回结果一致则返回 true, 否则返回 false */}export default React.memo(MyComponent, areEqual);

要探讨解决方案,让我们先验证一下函数组件是不是也有和类组件一样的无用渲染的问题。

不可突变的数据结构帮助我们轻松的追踪对象变化,从而可以快速的实现shouldComponentUpdate。

8使用 ComponentDidUnmount() 删除未使用的DOM 元素

首先我们先将ES6的TestC类转换为一个函数组件:

具体如何使用可参考下面文章:Immutable 详解及 React 中实践

有些时候,存在一些未使用的代码会导致内存泄漏的问题,React 通过向我们提供componentWillUnmount方法来解决这个问题。

import React from 'react';const TestC =  => { console.log(`Rendering TestC :` props) return (  {props.count}  )}export default TestC;// App.js

组件尽可能的进行拆分、解耦

componentWillUnmount()会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 定时器,取消网络请求或清除在componentDidMount()中创建的订阅等。

当上面的代码初次加载时,控制台的输出是:

组件尽可能的细分,比如一个input list组件,可以将list分成一个PureComponent,只在list数据变化时更新。否则在input值变化页面重新渲染的时候,list也需要进行不必要的DOM diff。

例如,我们可以在组件销毁之前,清除一些事件处理程序:

同样,我们可以打开Chrome的调试工具,点击React标签然后选中TestC组件:

列表类组件优化

componentWillUnmount() { document.removeEventListener("click", this.closeMenu);}

我们可以看到这个组件的参数值是5,让我们将这个值改为45, 这时候浏览器输出:

key属性在组件类之外提供了另一种方式的组件标识。通过key标识,在组件发生增删改、排序等操作时,可以根据key值的位置直接调整DOM顺序,告诉React 避免不必要的渲染而避免性能的浪费。例,对于一个基于排序的组件渲染:

componentWillUnmount()中不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。

由于count的值改变了,所以该组件也被重新渲染了,控制台输出Object{count: 45},让我们重复设置count的值为45, 然后再看一下控制台的输出结果:

var items = sortBy(this.state.sortingAlgorithm, this.props.items);return items.map{ return });

9其他优化技术虚拟化长列表如果你的应用渲染了长列表(上百甚至上千的数据),我们推荐使用“虚拟滚动”技术。这项技术会在有限的时间内仅渲染有限的内容,并奇迹般地降低重新渲染组件消耗的时间,以及创建 DOM 节点的数量。

由输出结果可以看出,即使count的值保持不变,还是45, 该组件还是被重渲染了。

当顺序发生改变时,React 会对元素进行diff操作,并改img的src属性。显示,这样的操作效率是非常低的。这时,我们可以为组件添加一个key属性以唯一的标识组件:

react-window 和 react-virtualized 是热门的虚拟滚动库。它们提供了多种可复用的组件,用于展示列表、网格和表格数据。如果你想要一些针对你的应用做定制优化,你也可以创建你自己的虚拟滚动组件,就像 Twitter 所做的。

既然函数组件也有无用渲染的问题,我们如何对其进行优化呢?

return 

使用 Chrome Performance 标签分析组件

解决方案: 使用React.memo()

增加key后,React就不是diff,而是直接使用insertBefore操作移动组件位置,而这个操作是移动DOM节点最高效的办法。

在开发模式下,你可以通过支持的浏览器可视化地了解组件是如何 挂载、更新以及卸载的。例如:

React.memo是React v16.6引进来的新属性。它的作用和React.PureComponent类似,是用来控制函数组件的重新渲染的。React.memo 其实就是函数组件的React.PureComponent

bind函数

在 Chrome 中进行如下操作:

如何使用React.memo?

绑定this的方式:一般有下面3种方式:

临时禁用所有的 Chrome 扩展,尤其是 React 开发者工具。他们会严重干扰度量结果!确保你是在 React 的开发模式下运行应用。打开 Chrome 开发者工具的Performance标签并按下Record。对你想分析的行为进行复现。尽量在 20 秒内完成以避免 Chrome 卡住。停止记录。

React.memo使用起来非常简单,假设你有以下的函数组件:

1、constructor绑定

在User Timing标签下会显示 React 归类好的事件。

const Funcomponent = ()=> { return (  Hiya!! I am a Funtional component  )}
constructor; this.handleClick = this.handleClick.bind; //构造函数中绑定}//然后可以

 { this.handleClick() }}/>

最后,我们探索了一些可以优化 React 应用程序的一些提高性能的方法,不局限于此。我们应该根据需要有针对性的优化应用程序,因为在某些简单的场景中,过度的优化,可能会得不偿失。

我们只需将上面的Funcomponent作为参数传入React.memo中:

以上三种方法,第一种最优。

来自:-WT8Muwiur8vo0qw

const Funcomponent = ()=> { return (  Hiya!! I am a Funtional component  )}const MemodFuncComponent = React.memo

因为第一种构造函数只在组件初始化的时候执行一次,

Web前端,React.memo会返回一个纯化的组件MemoFuncComponent,这个组件将会在JSX标记中渲染出来。当组件的参数props和状态state发生改变时,React将会检查前一个状态和参数是否和下一个状态和参数是否相同,如果相同,组件将不会被渲染,如果不同,组件将会被重新渲染。

第二种组件每次render都会执行

现在让我们在TestC组件上使用React.memo进行优化:

第三种在每一次render时候都会生成新的箭头函数。例:Test组件的click属性是个箭头函数,组件重新渲染的时候Test组件就会

let TestC =  => { console.log('Rendering TestC :', props) return (  { props.count } > )}TestC = React.memo;打开浏览器重新加载我们的应用。然后打开Chrome调试工具,点击React标签,然后选中组件。接着编辑一下props的值,将count改为89,我们将会看到我们的应用被重新渲染了:然后重复设置count的值为89:这就是React.memo这个函数牛X的地方!在我们之前那个没用到React.memo的例子中,count的重复设置会使组件进行重新渲染。可是我们用了React.memo后,该组件在传入的值不变的前提下是不会被重新渲染的。结论 React.PureComponent是银 React.memo是金 React.PureComponent是给ES6的类组件使用的 React.memo是给函数组件使用的 React.PureComponent减少ES6的类组件的无用渲染 React.memo减少函数组件的无用渲染 为函数组件提供优化是一个巨大的进步以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

因为这个新生成的箭头函数而进行更新,从而产生Test组件的不必要渲染。

不要滥用props

props尽量只传需要的数据,避免多余的更新,尽量避免使用{...props}

ReactDOMServer进行服务端渲染组件

为了用户会更快速地看到完整渲染的页面,可以采用服务端渲染技术,在此了解一下ReactDOMServer。

为了实现SSR,你可能会用nodejs框架来启动一个web服务器,接着调用 renderToString 方法去渲染你的根组件成为字符串,最后你再输出到 response。

// using Expressimport { renderToString } from "react-dom/server";import MyPage from "./MyPage";app.get => { res.write("My Page"); res.write; res.write(renderToString; res.write(""); res.end;

客户端使用render方法来生成HTML

import ReactDOM from 'react-dom';import MyPage from "./MyPage";ReactDOM.render(, document.getElementById;

react性能检测工具

react16版本之前,我们可以使用react-addons-perf工具来查看,而在最新的16版本,我们只需要在url后加上?react_pref。首先来了解一下react-addons-perf。

react-addons-perf这是 React 官方推出的一个性能工具包,可以打印出组件渲染的时间、次数、浪费时间等。简单说几个api,具体用法可参考官网:

Perf.start 结束记录 Perf.printInclusive() 查看所有设计到的组件render Perf.printWasted() 查看不需要的浪费组件render

再来了解一下,react16版本的方法,在url后加上?react_pref,就可以在chrome浏览器的performance,我们可以查看User Timeing来查看组件的加载时间。点击record开始记录,注意记录时长不要超过20s,否则可能导致chrome挂起。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

TAG标签:
版权声明:本文由澳门新葡8455手机版发布于Web前端,转载请注明出处:种优化技术,详解使用React