react函数能优化知识,React性能优化指南

seosqwseo4个月前 (09-15)测评日记37

一、React性能优化指南

使用React开发的项目,可以从加载性能和运行时性能两个方面进行优化。

加载性能优化的目标是让用户更早地看到界面、更早地和应用交互。运行时性能优化目标是降低卡顿,交互更流畅。

我们知道React的setState会触发diff和更新。默认是将整个组件树进行对比,但很多情况下diff是不必要的,因为一个子组件的props没有改变,就不需要进行diff工作。

为了避免这种对没有改变props的子组件进行多余的diff工作的情况,React提供了shouldComponentUpdate这个生命周期钩子, shouldComponentUpdate(nextProps, nextState)。这个生命周期钩子如果返回true,则会执行后面的render和diff工作,如果返回false,则React不会向下继续。用户可以在这个生命周期钩子中进行state和props的对比,判断是否需要更新。通常一个组件当前的props与nextProps属性值相同,并且state的属性值也相同,则不需要更新。

React.PureComponent实现了shouldComponentUpdate这个方法,PureComponent采用了浅比较,

【前端面试刷题网站:灵题库,收集大厂面试真题,相关知识点详细解析。】

对应class组件的PureComponent,函数组件有React.memo方法实现类似的效果。

React.memo

由于默认的PureComponent和memo都是默认用的浅比较。因此如果对象层级较深,会导致漏更新。

解决办法是,如果对象改变,重新创建一个对象,如果数组改变,重新创建一个数组,解构赋值可以很容易地实现这一点:{...oldData};[...oldArr]。

用户可以自己实现shouldComponentUpdate以自定义比较逻辑,对于函数式组件,则可以通过React.memo的第二个参数来定义比较逻辑。

如果想要精确地判断区别,除了手动判断,还有一个自动化程度比较高的方式:不可变数据,这时一个不可变数据的JS实现: immutable-js。

只有发生改动的节点会创建新的引用,因此相应的组件才会执行render和diff。

结论:佳实践是PureComponent/React.memo+不可变数据。

Fragment可以避免不必要的dom节点。

JSX的标签表达式要求有一个根节点

如果就想让表达式返回一个标签列表,不应该在外层加一个根节点,应该使用Fragment。

也可以简写

在注册**回调时候,不要用匿名函数或者用**nd生成新函数,应该用箭头函数或者构造里面**nd,好是构造函数里面**nd(因为可以继承)。

当我们需要注册**回调时候,可以写成这样写:

或者

上面这两种:匿名函数和**nd表达式,都不推荐。因为匿名函数的写**在每次调用render时候都创建新的函数,而**nd表达式也会在每次调用时候创建一个新的函数,React做diff时候发现**回调函数不同,就会将旧的函数解绑(这样还会触发GC)并且绑定新的函数。

因此好这样实现

或者

更推荐后者,因为我们知道:

class Test{log=()=>{};}和 class Test{log(){}}

这两种写法的区别在于前者log是类的实例方法,而后者是原型方法,因此在构造函数中绑定,能让其他使用原型继承方法继承Test的组件可以继承到log方法。

如果使用函数式组件,应该使用useCallback这个hook。关于useCallback的使用,请参考本知识库的React进阶一文。

因为React在解析JSX时候需要将style对象解析成css style字符串。更推荐将样式写在CSS中。

如果在render方法进行setState,可能导致循环地进行diff工作。

让条件分支中只包含需要改动的元素,不包含不需要改动的元素,防止diff子节点和更新节点时候增加不必要的*作,消耗性能。

示例:

应该改成下面这种写法:

我们知道,Vue中有计算属性的能力,能够根据依赖的数据计算出我们关心的数据,而且有缓存的能力:依赖的值不变的话,不需要计算,直接返回结果。

React如果想要实现根据依赖的数据计算我们关心的数据,方法很简单。

但是这样实现没有缓存值的能力,当计算耗时较长时候会影响性能。

如何实现缓存值的能力呢?

可以使用memorize-one这个库:

如果使用函数式组件,可以使用useMemo来实现。关于useMemo库的使用,请参考本讲义中React进阶一文。

react-vitualize

启用concurrent mode之后,React会采取可中断渲染,让大规模的diff计算不会影响到界面的渲染,保证渲染和交互的流畅性。

使用Suspense组件可以在加载局部组件时候有更好的切换加载体验。

concurrent详细的介绍请阅读本系列concurrent mode文章。

不使用key或者用index作为key,都可能使列表在变化时候,让React无法辨别前后item对应关系,只能遍历对比,更新属性,这样可能会有多余的*作,造成性能损耗。

为什么需要key呢?我会单独写一篇文章详细讲解。

React官方提供了一个性能检测工具: react-addons-perf。

这个工具可以在渲染React应用时候打印各个组件的各种耗时,用来分析性能浪费。

其中比较重要的一个方法是printWasted(),可以打印并未更新组件的渲染*作,如果发现你的组件花了很长时间render和diff,但组件视图实际并未发生变化,那就要考虑是否需要引入PureComponent等优化渲染性能了。

二、vue和react哪个更好用,为什么

Vue和React都是属于目前比较主流的前端框架,实际开发中也经常会拿Vue和React来比较。但是我们通常会根据各自优势来选择项目比较适合的框架。

React优点:

1.声明式设计−React采用声明范式,可以轻松描述应用。

2.高效−React通过对DOM的模拟,大限度地减少与DOM的交互。

3.灵活−React可以与已知的库或框架很好地配合。

4.JSX− JSX是 JavaScript语法的扩展。React开发不一定使用 JSX,但我们建议使用它。

5.组件−通过 React构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。

6.单向响应的数据流− React实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。

Vue优点:

1.简单易学,容易上手,Vue是国内团队开发,文档手册比较齐全,很适合前端新手小白学习。

2.更顺畅的集成:无论是单页应用程序还是复杂的Web界面,Vue.js都可以更平滑地集成更小的部件,而不会对整个系统产生任何影响。

3.性能优势,更小的尺寸:它占用更少的空间,并且往往比其他框架提供更好的性能。

精心编写的文档:通过详细的文档提供简单的学习曲线,无需额外的知识; HTML和JavaScript将完成工作。

4.运行速度快,相对于React来说,性能着一方面Vue占有绝大优势。

根据不同框架优点,我们在实际项目开发选型中一般中小型项目我们会选择使用Vue,大型项目会选择React。

三、React的Effect Hook解决函数组件的性能问题和潜在bug!

Hook是以 use开头的特殊函数,让函数组件拥有 calss组件的某些特性。Effect Hook就是指 useEffect这个特殊函数,它让函数组件能在渲染完成后执行自定义*作。

useEffect中要谨慎使用 useState,因为它会触发组件渲染后,再次调用 useEffect,形成一个死循环。正确方式:用条件语句包裹 useState方法,定义了退出条件,避开死循环。

让组件只监控特定数据的变更,再进行渲染后的*作,忽略不必要的*作,很好的优化了组件性能。

只有一个参数,每一次组件渲染完成后且在下一次渲染前被调用。

有两个参数,第二个参数是空数组( [])。在组件首次加载渲染完成后被调用,且只被调用这一次。

有两个参数,第二个参数是数组。只有当数组里面的值改变时, useEffect才会被调用。

useEffect被调用时,执行了一些*作(譬如设定了一个定时器、访问了一些网络资源),在组件卸载时,必须做一些清除*作来防止内存泄露等问题。

解决方案:只需要在 useEffect中返回一个清除函数,React会在组件卸载之前调用清除函数。

useEffect没有指定依赖,意味着 useEffect只会运行一次,其内部获取到的 count永远是初始值0,导致页面中的<h1>{count}</h1>值,永远是1。

在 useEffect中添加 count依赖,这样每一次 useEffect执行 setCount带来count的变化,都会使得 useEffect再次被调用,可以解决问题,但是这样会带来另一个问题,每一次执行 useEffect都会清除计时器,再重新设置计时器,这不是我们想要的。

采用 setState的更新特性,让 setCount自己去获取和更新 count,让 useEffect完全脱离对 count的依赖,实现终理想效果。

使用 useRef和 useEffect来实现,仅当你实在找不到更好办法的时候才这么做,因为依赖于变更会使得组件更难以预测。

useEffect会在组件完全渲染完后被调用执行,此时执行的 useEffect,如果涉及到可见DOM变更,就可能给客户带来视觉上的跳跃感,此时可以考虑使用 useLayoutEffect,使用方式跟 useEffect完全一样,只是被调用的时机不同。

相关文章

创维(Skyworth)创维电视50英寸50A3D怎么样?质量测评好不好用?

创维(Skyworth)创维电视50英寸50A3D怎么样?质量测评好不好用?

很多小伙伴在关注创维(Skyworth)创维电视50英寸50A3D怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使用分享和相应的优惠信息,为大家推荐一款高性价比的...

海信会议平板电视65英寸会议电视智能会议平板一体机触摸电视智慧大屏使用感受分享

海信会议平板电视65英寸会议电视智能会议平板一体机触摸电视智慧大屏使用感受分享

很多小伙伴在关注海信会议平板电视65英寸会议电视智能会议平板一体机触摸电视智慧大屏怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使用分享和相应的优惠信息,为大家推...

万宝(Wanbao)会议平板电视65英寸电子白板教学一体机触摸屏视频培训办公室智慧显示大屏幕4K教育无线投屏H6商用测评怎么样

万宝(Wanbao)会议平板电视65英寸电子白板教学一体机触摸屏视频培训办公室智慧显示大屏幕4K教育无线投屏H6商用测评怎么样

很多小伙伴在关注万宝(Wanbao)会议平板电视65英寸电子白板教学一体机触摸屏视频培训办公室智慧显示大屏幕4K教育无线投屏H6商用怎么样?质量好不好?使用测评如何?本文综...

康佳(KONKA)55V5D测评怎么样

康佳(KONKA)55V5D测评怎么样

很多小伙伴在关注康佳(KONKA)55V5D怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使用分享和相应的优惠信息,为大家推荐一款高性价比的产品,一起来看看吧。...

萤石(EZVIZ)C6c价格多少钱

萤石(EZVIZ)C6c价格多少钱

很多小伙伴在关注萤石(EZVIZ)C6c怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使用分享和相应的优惠信息,为大家推荐一款高性价比的产品,一起来看看吧。...

先科(SAST)V30红收音机老人老年人充电插卡迷你小音箱便携式半导体随身听fm调频广播音响音乐播放器使用心得反馈

先科(SAST)V30红收音机老人老年人充电插卡迷你小音箱便携式半导体随身听fm调频广播音响音乐播放器使用心得反馈

很多小伙伴在关注先科(SAST)V30红收音机老人老年人充电插卡迷你小音箱便携式半导体随身听fm调频广播音响音乐播放器怎么样?质量好不好?使用测评如何?本文综合已购用户的客...