React的核心开发团队一直在努力让React更快。可能有以下:方法可用于优化React中的组件性能
组件惰性加载(React.lazy(.)和挂起/)纯组件应该组件日期(.) {.}生命周期功能本文还将介绍React16.6特别添加的另一种优化Functional Component性能的方法。
无用的渲染
组件是构成反应视图的基本单元。一些组件将有自己的本地状态,当它们的值由于用户操作而改变时,这些组件将被重新呈现。在React应用程序中,组件可能会频繁呈现。这些渲染虽然有一部分是必要的,但大部分是无用的,它们的存在会大大降低我们应用的性能。
请看下面的例子:
从“React”导入React;TestC类扩展了React。组件{构造器(道具){ super(道具);this . state={ count : 0 } } component will update(nextProps,nextState){ console . log(' component will update ')} component diupdate(prev props,prev state){ console . log(' component diupdate ')} render(){ return(div { this . state . count }按钮onClick={()=this . setstate({ count : 1 })}单击Me/button/div;} }导出默认TestCTestC组件有一个本地状态计数,其初始值为0(state={count: 0})。当我们单击“单击我”按钮时,计数值设置为1。此时,屏幕上的数字将从0变为1。当我们再次点击按钮时,count的值仍然是1。此时,TestC组件不应该被重新渲染,但这是真的吗?
为了测试是否会重新呈现按计数重复设置相同值的组件,我为TestC组件添加了两个生命周期函数: componentWillUpdate和componentDidUpdate。当组件即将被重新呈现时,调用componentWillUpdate方法,在组件被成功重新呈现后,调用componentDidUpdate方法。
在浏览器中运行我们的代码,然后多次点击Click Me按钮,可以看到如下输出:
我们可以看到,每次单击按钮时,控制台上会输出“componentwillupdate”和“componentwillupdate”。因此,即使计数被设置为相同的值,TestC组件仍然会被重新渲染,这被称为无用渲染。
纯组件/应该组件更新
为了避免对React组件进行无用的渲染,我们可以实现自己的shouldComponentUpdate生命周期函数。
当React想要渲染一个组件时,它会调用该组件的shouldComponentUpdate函数,该函数会告诉它是否真的想要渲染该组件。
如果我们的shouldComponentUpdate函数这样写:
ShouldComponentUpdate(下一个道具,下一个状态){return true}每个参数的含义是:
nextProps:组件将接收的下一个参数,props:组件的下一个状态,state,因为我们的shouldComponentUpdate函数总是返回true,这告诉React无论如何都要重新呈现组件。
但是如果我们这样写:
should component update(next props,nextstate) {return false}由于此方法的返回值为false,React将永远不会重新呈现我们的组件。
所以当你想要React重新渲染你的组件时,在这个方法中返回true,否则返回false。现在让我们用shouldComponentUpdate重写之前的TestC组件:
从“React”导入React;TestC类扩展了React。组件{构造器(道具){ super(道具);this . state={ count : 0 } } component will update(nextProps,nextState){ console . log(' component will update ')} component update(previprops,previstate){ console . log(' component update ')} should component update(nextProps,nextState){ if(this . state . count===nextState . count){ return false } return true } render(){ return(div { this . state . count }按钮onClick={()=this . setstate({ count 3336} }导出默认TestC我们在TestC组件中加入了shouldComponentUpdate方法,判断如果当前状态的计数和下一个状态的计数相同,我们将返回false,这样React就不会重新渲染组件;否则,如果两个值不同,它将返回true,这样组件将重新呈现。
再次,在浏览器中测试我们的组件。一开始的界面是这样的:
此时,即使我们多次点击Click Me按钮,也只能看到两行输出:
组件更新组件更新
由于第二次单击“单击我”按钮后计数值始终为1,因此shouldComponentUpdate始终返回false,组件将不会重新呈现。
那么,如何验证组件在状态值改变后仍然会被重新呈现呢?我们可以在浏览器的React DevTools插件中直接更改TestC组件的状态。具体来说,点击Chrome调试工具中的React选项卡,选择界面左侧的TestC组件。在界面的右侧,可以看到其状态下只有一个键数,其值为1:
然后让我们点击计数的值1,将其更改为2,然后按回车键:
您将看到控制台有以下输出:
组件更新组件更新组件更新组件更新组件更新
状态计数已更改,组件已重新呈现。
现在让我们使用另一种方法,PureComponent,来优化组件。
在第15.5节中,通过反应引入了纯组分成分.在更新组件时,如果React发现该组件是PureComponent,它会对组件的当前状态和道具与其下一个状态和道具进行一个粗浅的比较。如果它们的值没有改变,就不会更新。要使您的组件成为纯组件,您只需要扩展React.PureComponent
让我们用PureComponent :重写我们的代码
从“React”导入React;TestC类扩展了React。PureComponent {构造器(道具){ super(道具);this . state={ count : 0 } } component will update(nextProps,nextState){ console . log(' component will update ')} component update(previprops,previstate){ console . log(' component update ')}/* should component update(nextProps,nextState){ if(this . state . count===nextState . count){ return false } return true } */render(){ return(div { this . state . count }按钮onClick={()=this . setstate({ count} }导出默认TestC在上面的代码中,我注释掉了shouldComponentUpdate的代码,因为React。PureComponent本身可以帮助我们实现同样的功能。
更改代码后,我们刷新浏览器,然后多次单击“单击我”按钮,查看组件被渲染了多少次:
从上面的输出可以看出,只有当状态从0变为1时,我们的组件才会被重新渲染,之后不会执行渲染。
功能组件
上面,我们讨论了如何通过使用purecomponentupdate和shouldComponentUpdate来优化类组件的性能。虽然类组件是React应用程序的主要组件,但功能组件也可以用作React组件。
函数测试c (props) {return (div我是函数组件/div)}对于函数组件来说,它们没有状态之类的东西来保存它们的本地状态(虽然函数组件可以在React Hooks中使用useState来使用状态),所以我们不能像在类组件中使用shouldComponentUpdate之类的life函数那样控制函数组件的重新呈现。当然,我们不能使用extendsreport。purecomponent也是,因为它根本不是一个类。
为了探索解决方案,让我们首先验证函数组件是否存在与类组件相同的无用呈现问题。
首先,我们首先把ES6的TestC类转换成一个函数组件:
从“React”导入React;const TestC=(道具)={ console . log(` rendering TeStc : ` props)return(div { props . count }/div)}导出默认TeStc;//app . jstestc count={ 5 }/首次加载上述代码时,控制台的输出为:
同样,我们可以打开Chrome的调试工具,点击React选项卡,选择TestC组件:
我们可以看到这个组件的参数值是5,让我们把这个值改成45,然后浏览器输出:
由于count的值已更改,组件已被重新呈现。控制台输出对象{count: 45}。让我们反复设置count的值为45,然后看看console :的输出结果。
从输出中可以看出,即使count的值保持不变,它仍然是45,组件被重新渲染。
既然功能组件也有无用渲染的问题,那怎么优化呢?
解决方案:使用React.memo()
反应备忘录(.)是React v16.6引入的新属性.它的功能类似于React。它用于控制功能组件的重新呈现。反应备忘录(.)其实就是React。函数组件的PureComponent。
如何使用React.memo(.)?
React.memo的使用非常简单,假设您有以下功能组件:
const Funcomponent=()={ return(div Hiya!我是一个功能组件/div)}我们只需要将上面的功能组件作为参数传入React.memo:
const Funcomponent=()={ return(div Hiya!我是一个功能组件/div)} const memofunccomponent=react . memo(funcomponent)react . memo将返回一个纯化的组件memofuncomponent,它将以JSX标记呈现。当组件的参数道具和状态状态发生变化时,React会检查前一个状态和参数是否与下一个状态和参数相同。如果它们相同,则不会渲染组件,但如果它们不同,则会重新渲染。
现在让我们使用TestC组件上的React.memo来优化:
让TestC=(道具)={ console . log(' Rendering TeStc : ',道具)返回(div { props . count }/)} TeStc=react . memo(TeStc);打开浏览器,重新加载我们的应用程序。然后打开Chrome调试工具,点击React选项卡,然后选择Memo(TestC)组件。
然后编辑道具的值并将计数更改为89,我们将看到我们的应用程序已经被:重新渲染
然后反复将count的值设置为89:
这里没有重渲染!
这就是函数React.memo(.)有X的优势!
在我们前面的例子中,React.memo(.)时,重复设置count会导致重新呈现组件。但是,在我们使用React.memo之后,如果传入的值不变,组件将不会被重新呈现。
结论
以下是:的总结
反应。PureComponent是银React.memo(.)是金的反应。PureComponent用于ES6的类组件。它用于功能组件,以减少ES6的类组件的无用呈现。减少功能组件的无用渲染,为功能组件提供优化是一个很大的进步。以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。