内容简介:总结了以下几个方面在react上的性能优化在开发前期可以根据业务场景将组件分类这里我们就要说一下有状态组件和无状态组件的区别了 就如上所说的展示类组件,这种我们就可以把它归类为无状态组件,举个列子
总结了以下几个方面在react上的性能优化
-
常见的性能问题场景
-
时刻注意代码的潜在性能问题
-
注意可重构的代码,组件化
-
了解如何使用 工具 定位性能问题
常见的性能问题场景
-
JavaScript 语言采用的是单线程模型,也就是说,所有任务只能在一个线程上完成,一次只能做一件事。如果页面比较负责,添加了大量的计算,并且还添加了Canvas(Canvas 是一个非常受欢迎的表现方式,同时也是WebGL的入口。它能绘制图形,图片,展示动画,甚至是处理视频内容)的绘制,那页面加载可能会卡顿,有可能会呈现出假死状态。
解决方案:在Worker中使用OffscreenCanvas或者将页面渲染时大量的计算放在Worker中。 首先我们先了解几个概念(以在Worker中用OffscreenCanvas为列)
-
Workers 是一个Web版的线程——它允许你在幕后运行你的代码。将你的一部分代码放到Worker中可以给你的主线程更多的空闲时间,这可以提高你的用户体验度
-
OffscreenCanvas并不依赖DOM。
- 一种是在 Worker 线程创建一个 OffscreenCanvas 做后台渲染,然后再把渲染好的缓冲区 Transfer 回主线程显示。
- 一种是主线程从当前 DOM 树中的 Canvas 元素产生一个 OffscreenCanvas,再把这个 OffscreenCanvas 发送给 Worker 线程进行渲染,渲染的结果直接 Commit 到浏览器的 Display Compositor 输出到当前窗口,相当于在 Worker 线程直接更新 Canvas 元素的内容。
-
OffscreenCanvas学习文档 developers.google.com/web/updates… 。
另外web workers学习文档请去官网了解
developer.mozilla.org/en-US/docs/…
总结: 学习成本比较低,在耗性能的计算和渲染放在Worker中,确实能提升用户体验度
-
-
dom节点层次多,而且深,更改state或者更改redux,导致与该数据无相关的dom节点多次render。
-
js处理数据过于复杂。定义的状态数据层次过于深。导致对比或者遍历数据消耗性能。
时刻注意代码的潜在性能问题
-
{...this.props}不要滥用,请只传递component需要的props,传得太多,或者层次传得太深,都会加重shouldComponentUpdate里面的数据比较负担。
-
方法绑定的使用
- 方法直接绑定在dom节点中
<div onClick={this.tap.bind(this)} /> 复制代码
- 方法绑定放在constructor中
constructor(props) { super(props); this.tap= this.tap.bind(this); } 复制代码
- 箭头函数
tap = ()=>{}; <div onClick={this.tap} /> 复制代码
tap =(value)=> {}; <div onClik={()=>this.tap(value)} /> 复制代码
总结:
1.由于绑定是在render中执行,而render是会执行多次的,每次bind和箭头函数都会产生一个新的函数,因而带来了额外的开销2.使用构造器bind的方法,每个实例都可以有效地共享函数体,从而更加有效的使用内存。但当要绑定的函数较多时,这种方法又显得相对的枯燥和无聊。所以,在知道实例不多,函数体不大的前提下,使用箭头函数更加快捷。
3.综合三种写法,第三种是目前最优写法
-
数组遍历map
map里面添加key,并且key不要使用index(可变的),尽量使用稳定常量作为key。使用index作为key,只是会让代码不报错,其他一无是处。 每当组件的props或state改变时, React会重新创建一个virtual DOM, 与上一个作对比, 如果发现两个virtual DOM不完全相同, 则React就会做reconcile, 把有差异的地方更新到真实的DOM上。 使用常量作为key 复制代码
-
尽量少用不可控的refs、DOM操作。
-
props和state的数据尽可能简单明了,扁平化。便于数据对比,数组遍历从而减小带来的性能消耗。
-
使用return null而不是CSS的display:none来控制节点的显示隐藏。保证同一时间页面的DOM节点尽可能的少。
注意可重构的代码,组件化
- 组件分类
- 可复用性
- 足够细
- 耦合度低
组件分类
在开发前期可以根据业务场景将组件分类
- 展示类组件(没有任何交互,只是纯展示数据)
- 交互类组件(页面交互操作比较频繁)
- 数据类组件(比如dva,redux,基本在搭建框架时已模块化)
- 高阶组件(对原有组件的保护,更利于后续的迭代开发)
可复用性
这里我们就要说一下有状态组件和无状态组件的区别了 就如上所说的展示类组件,这种我们就可以把它归类为无状态组件,举个列子
import React from 'react'; const PicModal = props => { const { title = '', content = '', picUrl = '', deviceName = '' } = props; return ( <div> <span>title</span> <span>content</span> <span>deviceName</span> {picUrl !== '' ? <img src={picUrl}/> : null} </div> ); }; export default PicModal; 复制代码
这样我们就可以自己封装一个modal组件,根据业务场景不断的迭代优化。 而上面的交互类组件大多数情况下都是有状态组件,维护自身的状态值。但是要实现可复用性,组件之间的耦合度肯定是要低的。组件自己控制自己内部的state。这样setState只用局部更新视图。减小性能消耗。
注意:千万不要在父组件定义state,传值给子组件。
1.降低组件之间的耦合度
2.便于后续的组件迭代
足够细
根据业务场景将组件拆分的足够细。
- 可读性强
- 维护性高
- 便于复用
耦合度低
下面举一个移动端的列子,web端大多数都会有这种情况,点击项目id列表中projectId,projectList改变。
解决方案:组件1和组件2是通过projectId进行联动。如果我们拿到这个需求,首先组件化1和2,组件1通过点击id,在父组件中执行getProjectList方法,从而实现渲染组件2。根据组件1中id的state渲染组件1
这样父组件与子组件耦合度很低,子组件自己维护自己的状态值
兄弟组件之间互不影响,通过父组件通信
如果拆分业务组件的思路不清晰,盲目的将状态值放在父组件中,这样耦合度会大大增加,组件的复用性会大大降低。
了解如何使用工具定位性能问题
- chrome插件 redux devtools
- chrome插件 react devtools
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
反应式设计模式
Roland Kuhn、Brian Hanafee、Jamie Allen / 何品、邱嘉和、王石冲、林炜翔审校 / 清华大学出版社 / 2019-1-1 / 98.00 元
《反应式设计模式》介绍反应式应用程序设计的原则、模式和经典实践,讲述如何用断路器模式将运行缓慢的组件与其他组件隔开、如何用事务序列(Saga)模式实现多阶段事务以及如何通过分片模式来划分数据集,分析如何保持源代码的可读性以及系统的可测试性(即使在存在许多潜在交互和失败点的情况下)。 主要内容 ? “反应式宣言”指南 ? 流量控制、有界一致性、容错等模式 ? 得之不易的关于“什么行不通”的经验 ? ......一起来看看 《反应式设计模式》 这本书的介绍吧!