react性能优化
前面的话
本文将详细介绍react性能优化
避免重复渲染
当一个组件的props
或者state
改变时,React通过比较新返回的元素和之前渲染的元素来决定是否有必要更新实际的DOM。当他们不相等时,React会更新DOM。
在一些情况下,组件可以通过重写这个生命周期函数shouldComponentUpdate
来提升速度, 它是在重新渲染过程开始前触发的。 这个函数默认返回true
,可使React执行更新:
shouldComponentUpdate(nextProps, nextState) {
return true;
}
如果知道在某些情况下组件不需要更新,可以在shouldComponentUpdate
内返回false
来跳过整个渲染进程,该进程包括了对该组件和之后的内容调用render()
指令
如果想让组件只在props.color
或者state.count
的值变化时重新渲染,可以像下面这样设定shouldComponentUpdate
shouldComponentUpdate(nextProps, nextState) {
if (this.props.color !== nextProps.color) {
return true;
}
if (this.state.count !== nextState.count) {
return true;
}
return false;
}
【pureComponent】
在以上代码中,shouldComponentUpdate
只检查props.color
和state.count
的变化。如果这些值没有变化,组件就不会更新。当组件变得更加复杂时,可以使用类似的模式来做一个“浅比较”,用来比较属性和值以判定是否需要更新组件。这种模式十分常见,因此React提供了一个辅助对象来实现这个逻辑 - 继承自React.PureComponent
。以下代码可以更简单的实现相同的操作:
class CounterButton extends React.PureComponent {
constructor(props) {
super(props);
this.state = {count: };
} render() {
return (
<button
color={this.props.color}
onClick={() => this.setState(state => ({count: state.count + }))}>
Count: {this.state.count}
</button>
);
}
}
大部分情况下,可以使用React.PureComponent
而不必写自己的shouldComponentUpdate
,它只做一个浅比较。但是由于浅比较会忽略属性或状态突变的情况,此时不能使用它
避免突变
PureComponent
将会在this.props.words
的新旧值之间做一个简单的比较。由于代码中words
数组在WordAdder
的handleClick
方法中被改变了,尽管数组中的实际单词已经改变,this.props.words
的新旧值还是相等的,因此即便ListOfWords
具有应该被渲染的新单词,它还是不会更新。
handleClick() {
// This section is bad style and causes a bug
const words = this.state.words;
words.push('marklar');
this.setState({words: words});
}
避免此类问题最简单的方式是避免使用值可能会突变的属性或状态。例如,上面例子中的handleClick
应该用concat
重写成:
handleClick() {
this.setState(prevState => ({
words: prevState.words.concat(['marklar'])
}));
}
或者使用展开运算符
handleClick() {
this.setState(prevState => ({
words: [...prevState.words, 'marklar'],
}));
};
也可以用相似的方式重写可以会突变的对象。例如,假设有一个叫colormap
的对象,我们想写一个把colormap.right
改变成'blue'
的函数,我们应该写:
function updateColorMap(colormap) {
colormap.right = 'blue';
}
想要实现代码而不污染原始对象,我们可以使用Object.assign方法
function updateColorMap(colormap) {
return Object.assign({}, colormap, {right: 'blue'});
}
或者使用扩展运算符
function updateColorMap(colormap) {
return {...colormap, right: 'blue'};
}
immutable
Immutable.js是解决这个问题的另一种方法。它通过结构共享提供不可突变的,持久的集合
1、不可突变:一旦创建,集合就不能在另一个时间点改变
2、持久性:可以使用原始集合和一个突变来创建新的集合。原始集合在新集合创建后仍然可用
3、结构共享:新集合尽可能多的使用原始集合的结构来创建,以便将复制操作降至最少从而提升性能
不可突变数据使得变化跟踪很方便。每个变化都会导致产生一个新的对象,因此只需检查索引对象是否改变。例如,在这个常见的JavaScript代码中:
const x = { foo: 'bar' };
const y = x;
y.foo = 'baz';
x === y; // true
虽然y
被编辑了,但是由于它与x
索引了相同的对象,这个比较会返回true
。可以使用immutable.js
实现类似效果:
const SomeRecord = Immutable.Record({ foo: null });
const x = new SomeRecord({ foo: 'bar' });
const y = x.set('foo', 'baz');
x === y; // false
在这个例子中,x突变后返回了一个新的索引,因此我们可以安全的确认x被改变了
还有两个库可以帮助我们使用不可突变数据:seamless-immutable 和immutability-helper。 实现shouldComponentUpdate时,不可突变的数据结构帮助我们轻松的追踪对象变化。这通常可以提供一个不错的性能提升
react性能优化的更多相关文章
- React性能优化记录(不定期更新)
React性能优化记录(不定期更新) 1. 使用PureComponent代替Component 在新建组件的时候需要继承Component会用到以下代码 import React,{Componen ...
- 关于React性能优化
这几天陆陆续续看了一些关于React性能优化的博客,大部分提到的都是React 15.3新加入的PureComponent ,通过使用这个类来减少React的重复渲染,从而提升页面的性能.使用过Rea ...
- React性能优化之PureComponent 和 memo使用分析
前言 关于react性能优化,在react 16这个版本,官方推出fiber,在框架层面优化了react性能上面的问题.由于这个太过于庞大,我们今天围绕子自组件更新策略,从两个及其微小的方面来谈rea ...
- React 性能优化 All In One
React 性能优化 All In One Use CSS Variables instead of React Context https://epicreact.dev/css-variables ...
- React 性能优化总结
初学者对React可能满怀期待,觉得React可能完爆其它一切框架,甚至不切实际地认为React可能连原生的渲染都能完爆--对框架的狂热确实会出现这样的不切实际的期待.让我们来看看React的官方是怎 ...
- react 性能优化
React 最基本的优化方式是使用PureRenderMixin,安装工具 npm i react-addons-pure-render-mixin --save,然后在组件中引用并使用 import ...
- React性能优化总结(转)
原文链接: https://segmentfault.com/a/1190000007811296?utm_source=tuicool&utm_medium=referral 初学者对Rea ...
- react性能优化要点
1.减少render方法的调用 1.1继承React.PureComponent(会自动在内部使用shouldComponentUpdate方法对state或props进行浅比较.)或在继承自Reac ...
- React性能优化总结
本文主要对在React应用中可以采用的一些性能优化方式做一下总结整理 前言 目的 目前在工作中,大量的项目都是使用react来进行开展的,了解掌握下react的性能优化对项目的体验和可维护性都有很大的 ...
随机推荐
- ELK 日志采集 实战教程
概要 带着问题去看教程: 不是用logstash来监听我们的日志,我们可以使用logback配置来使用TCP appender通过TCP协议将日志发送到远程Logstash实例. 我们可以使用Logs ...
- 博弈论进阶之Multi-SG
Multi-Nim 从最简单的Nim模型开始 它的定义是这样的 有\(n\)堆石子,两个人可以从任意一堆石子中拿任意多个石子(不能不拿)或把一堆数量不少于\(2\)石子分为两堆不为空的石子,没法拿的人 ...
- iOS----------常用三方库
1.笔者常用三方库 名称 作用 说明 <small>AFNetworking <small>基于HTTP/HTTPS 联网请求 <small> <small& ...
- QT 启动shell脚本
1.QProcess *p = new QProcess(this); 2.QString str = qApp->applicationDirPath() + "/update.sh ...
- redis 五大数据结构__常用命令
linux 下下载redis数据库 apt install redis 如果提示权限不够的话, 直接提权: sudo apt install redis-server linux启用.停止服务 ser ...
- ubuntu 通过apt安装jdk
需要先添加ppa sudo add-apt-repository ppa:webupd8team/java sudo apt-get update 安装jdk8 sudo apt-get instal ...
- asp.net core 2.1 部署 centos7
asp.net core 2.1 部署 centos7 Kestrel 非常适合从 ASP.NET Core 提供动态内容. 但是,Web 服务功能不像服务器(如 IIS.Apache 或 Nginx ...
- 播放器的书签--推荐使用Potplayer
VLC Player https://www.vlchelp.com/skipping-and-playing-audio-and-video-portions-in-vlc/ PotPlayer ...
- 固态+机械双硬盘分别安装Win10和Ubuntu16.04双系统
博主的笔记本是256G固态+1T机械,固态事先已经安装好了Win10系统,想着把机械硬盘分出500G用来安装Ubuntu16.04,剩余的继续用作Win下的资料盘.这里不介绍安装Win10过程,也不记 ...
- 无法启动mysql服务”1067 进程意外终止”解决办法【简记】
本文章主要是总结了各种导致mysql提示无法启动MYSQL服务”1067 进程意外终止”的一些解决办法,有碰到mysql无法启动的同学可尝试参考. 在win7的服务器里开启MySql服务提示“wind ...