React组件性能优化总结
性能优化的思路
影响网页性能最大的因素是浏览器的重排(repaint)和重绘(reflow)。
React的Virtual DOM就是尽可能地减少浏览器的重排和重绘。
从React渲染过程来看,如何防止不必要的渲染是解决问题的关键。
性能优化的具体办法
1. 尽量多使用无状态函数构建组件
无状态组件只有props和context两个参数。它不存在state,没有生命周期方法,组件本身即有状态组件构建方法中的render方法。
在合适的情况下,都应该必须使用无状态组件。无状态组件不会像React.createClass和ES6 class会在调用时创建新实例,它创建时始终保持了一个实例,避免了不必要的检查和内存分配,做到了内部优化。
2. 拆分组件为子组件,对组件做更细粒度的控制
相关重要概念: 纯函数
纯函数的三大构成原则:
- 给定相同的输入,它总是返回相同的输出: 比如反例有 Math.random(), New Date()
- 过程没有副作用:即不能改变外部状态
- 没有额外的状态依赖:即方法内部的状态都只能在方法的生命周期内存活,这意味着不能在方法内使用共享的变量。
纯函数非常方便进行方法级别的测试及重构,它可以让程序具有良好的扩展性及适应性。纯函数是函数式变成的基础。
React组件本身就是纯函数,即传入指定props得到一定的Virtual DOM,整个过程都是可预测的。
具体办法
拆分组件为子组件,对组件做更细粒度的控制。保持纯净状态,可以让方法或组件更加专注(focus),体积更小(small),更独立(independent),更具有复用性(reusability)和可测试性(testability)。
3. 运用PureRender,对变更做出最少的渲染
相关重要概念: PureRender
PureRender的Pure即是指满足纯函数的条件,即组件被相同的props和state渲染会得到相同的结果。
在React中实现PureRender需要重新实现shouldComponentUpdate生命周期方法。shouldComponentUpdate是一个特别的方法,它接收需要更新的props和state,其本质是用来进行正确的组件渲染。当其返回false的时候,不再向下执行生命周期方法;当其返回true时,继续向下执行。
组件在初始化过程中会渲染一个树状结构,当父节点props改变的时候,在理想情况下只需渲染一条链路上有关props改变的节点即可;但是,在默认情况下shouldComponentUpdate方法返回true,React会重新渲染所有的节点。
有一些官方插件实现了对shouldComponentUpdate的重写,然后自己也可以做一些代码的优化来运用PureRender。
具体办法
(1) 运用PureRender
使用官方插件react-addons-pure-render-mixin实现对shouldComponentUpdate的重写
import React from 'react';
import PureRenderMixin from 'react-addons-pure-render-mixin';
class App extends React.Component {
constructor(props) {
super(props);
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
}
render() {
return <div className={this.props.className}>foo</div>
}
}
它的原理是对object(包括props和state)做浅比较,即引用比较,非值比较。比如只用关注props中每一个是否全等(如果是prop是一个对象那就是只比较了地址,地址一样就算是一样了),而不用深入比较。
(2)优化PureRender
避免无论如何都会触发shouldComponentUpdate返回true的代码写法。
避免直接为prop设置字面量的数组和对象
就算每次传入的数组或对象的值没有变,但它们的地址也发生了变化。
如以下写法每次渲染时style都是新对象都会触发shouldComponentUpdate为true:
<Account style={{color: 'black'}} />
改进办法:将字面量设置为一个引用:
const defaultStyle = {};
<Account style={this.props.style || defaultStyle} />
避免每次都绑定事件
如果这样绑定事件的话每次都要生成一个新的onChange属性的值:
render() {
return <input onChange={this.handleChange.bind(this)} />
}
应该尽量在构造函数内进行绑定,如果绑定需要传参那么应该考虑抽象子组件或改变现有数据结构:
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange() {
...
}
render() {
return <input onChange={this.handleChange} />
}
在设置子组件的时候要在父组件级别重写shouldComponentUpdate
4.运用immutable
JavaScript中对象一般是可变的,因为使用引用赋值,新的对象的改变将影响原始对象。为了解决这个问题是使用深拷贝或者浅拷贝,但这样做又造成了CPU和内存的浪费。
Immutable data很好地解决了这个问题。
Immutable data就是一旦创建,就不能再更改的数据。对Immutable对象进行修改、添加或删除操作,都会返回一个新的Immutable对象。Immutable实现的原理是持久化的数据结构。即使用旧数据创建新数据时,保证新旧数据同时可用且不变。同时为了避免深拷贝带来的性能损耗,Immutable使用了结构共享(structural sharing),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其他节点则进行共享。
React组件性能优化总结的更多相关文章
- React 组件性能优化
React组件性能优化 前言 众所周知,浏览器的重绘和重排版(reflows & repaints)(DOM操作都会引起)才是导致网页性能问题的关键.而React虚拟DOM的目的就是为了减少浏 ...
- React 组件性能优化探索实践
转自:http://www.tuicool.com/articles/Ar6Zruq React本身就非常关注性能,其提供的虚拟DOM搭配上Diff算法,实现对DOM操作最小粒度的改变也是非常的高效. ...
- React组件性能优化
转自:https://segmentfault.com/a/1190000006100489 React: 一个用于构建用户界面的JAVASCRIPT库. React仅仅专注于UI层:它使用虚拟DOM ...
- react组件性能优化PureComponent
首先我们使用react组件会配合connect来连接store获取state,那么只要store中的state发生改变组件就会重新渲染,所以性能不高,一般我们可以使用shouldComponentUp ...
- 如何对react进行性能优化
React本身就非常关注性能,其提供的虚拟DOM搭配上DIff算法,实现对DOM操作最小粒度的改变也是非常高效的,然而其组件的渲染机制,也决定了在对组件更新时还可以进行更细致的优化. react组件 ...
- React Native 性能优化指南【全网最全,值得收藏】
2020 年谈 React Native,在日新月异的前端圈,可能算比较另类了.文章动笔之前我也犹豫过,但是想到写技术文章又不是赶时髦,啥新潮写啥,所以还是动笔写了这篇 React Native 性能 ...
- React拖拽组件Dragact V0.1.7:教你优化React组件性能与手感
仓库地址:Dragact手感丝滑的拖拽布局组件 预览地址:支持手机端噢- 上回我们说到,Dragact组件已经进行了一系列的性能优化,然而面对大量数据的时候,依旧比较吃力,让我们来看看,优化之前的Dr ...
- React组件性能调优
React是一个专注于UI层的框架,它使用虚拟DOM技术,以保证它UI的高速渲染:使用单向数据流,因此它数据绑定更加简单:那么它内部是如何保持简单高效的UI渲染呢?这种渲染机制有可能存在什么性能问题呢 ...
- React项目性能优化
1. 使用生产版本和Fragment 1. 生产版本 确保发布的代码是生产模式下(压缩)打包的代码. 一般运行npm run build命令. 直接从webpack看配置文件,需要设置mode = ' ...
随机推荐
- camera frame work v3 note
1 android_atomic_write(level, &gLogLevel); 原子写操作. 2 构造函数和onFirstRef onFirstRef 会在构造函数运行后执行,这个是在m ...
- C语言细节注意
前段时间用C语言写了个小的程序,也算是复习了下好久没有用的C语言.也是有好多的坑了,哈哈. 1.C语言的结构体 结构体的命名最好能够做到规范.因为不同的 编译环境下,不是很规范的命名有时候会导致莫名其 ...
- Spring Boot 中配置切换
步骤一:切换需求 有时候在本地测试是使用8080端口(默认端口),可是上线时使用的比如是9090端口(不常用的,以防被黑). 此时就可以通过多配置文件实现多配置支持与灵活切换. 步骤二:多配置文件 3 ...
- EF Code-First 学习之旅 EntityTypeConfiguration<TEntity>
之前我们配置的实体都都在OnModelCreating方法中,如果有很多实体的话,OnModelCreating方法管理很麻烦 我们可以用单独的类来管理配置,继承EntityTypeConfigura ...
- Permutations,全排列
问题描述:给定一个数组,数字中数字不重复,求所有全排列. 算法分析:可以用交换递归法,也可以用插入法. 递归法:例如,123,先把1和1交换,然后递归全排列2和3,然后再把1和1换回来.1和2交换,全 ...
- LeetCode 之 TwoSum
题目: Given an array of integers, find two numbers such that they add up to a specific target number. ...
- ssm框架搭建流程及原理分析
这几天自己想搭建个ssm框架玩一下,有些东西长时间不玩都给忘了,所以自己把整个流程整理了一下,只要跟着步骤,就能顺利完成ssm框架的搭建. 一.搭建步骤: 1.整理jar包 2.对于一个web ...
- LeetCode第[56]题(Java):Merge Intervals
题目:合并区间 难度:Medium 题目内容: Given a collection of intervals, merge all overlapping intervals. 翻译: 给定一个 ...
- HYSBZ - 2818莫比乌斯反演
链接 题意很简洁不说了 题解:一开始我想直接暴力,复杂度是O(log(1e7)*sqrt(1e7))算出来是2e9,可能会复杂度爆炸,但是我看时限是10s,直接大力莽了一发暴力,没想到就过了= = 就 ...
- 使用swagger作为restful api的doc文档生成——从源码中去提取restful URL接口描述文档
初衷 记得以前写接口,写完后会整理一份API接口文档,而文档的格式如果没有具体要求的话,最终展示的文档则完全决定于开发者的心情.也许多点,也许少点.甚至,接口总是需要适应新需求的,修改了,增加了,这份 ...