React之PureComponent的使用作用


Posted in Javascript onJuly 10, 2018

React避免重复渲染

React在渲染出的UI内部建立和维护了一个内层的实现方式,它包括了从组件返回的React元素。这种实现方式使得React避免了一些不必要的创建和关联DOM节点,因为这样做可能比直接操作JavaScript对象更慢一些,它被称之为“虚拟DOM”。

当一个组件的props或者state改变时,React通过比较新返回的元素和之前渲染的元素来决定是否有必要更新实际的DOM。当他们不相等时,React会更新DOM。

在一些情况下,你的组件可以通过重写这个生命周期函数shouldComponentUpdate来提升速度, 它是在重新渲染过程开始前触发的。 这个函数默认返回true,可使React执行更新:

shouldComponentUpdate(nextProps, nextState) {
 return true;
}

举例

如果想让组件只在props.color或者state.count的值变化时重新渲染,你可以像下面这样设定shouldComponentUpdate

class CounterButton extends React.Component {
 constructor(props) {
  super(props);
  this.state = {count: 1};
 }

 shouldComponentUpdate(nextProps, nextState) {
  if (this.props.color !== nextProps.color) {
   return true;
  }
  if (this.state.count !== nextState.count) {
   return true;
  }
  return false;
 }

 render() {
  return (
   <button
    color={this.props.color}
    onClick={() => this.setState(state => ({count: state.count + 1}))}>
    Count: {this.state.count}
   </button>
  );
 }
}

在以上代码中,shouldComponentUpdate只检查props.colorstate.count的变化。如果这些值没有变化,组件就不会更新。当你的组件变得更加复杂时,你可以使用类似的模式来做一个“浅比较”,用来比较属性和值以判定是否需要更新组件。这种模式十分常见,因此React提供了一个辅助对象来实现这个逻辑 - 继承自React.PureComponent。以下代码可以更简单的实现相同的操作:

class CounterButton extends React.PureComponent {
 constructor(props) {
  super(props);
  this.state = {count: 1};
 }

 render() {
  return (
   <button
    color={this.props.color}
    onClick={() => this.setState(state => ({count: state.count + 1}))}>
    Count: {this.state.count}
   </button>
  );
 }
}

PureComponent

原理

当组件更新时,如果组件的 props 和 state 都没发生改变, render 方法就不会触发,省去 Virtual DOM 的生成和比对过程,达到提升性能的目的。具体就是 React 自动帮我们做了一层浅比较:

if (this._compositeType === CompositeTypes.PureClass) {
  shouldUpdate = !shallowEqual(prevProps, nextProps) || !shallowEqual(inst.state, nextState);
}

而 shallowEqual 又做了什么呢?会比较 Object.keys(state | props) 的长度是否一致,每一个 key 是否两者都有,并且是否是一个引用,也就是只比较了第一层的值,确实很浅,所以深层的嵌套数据是对比不出来的。

问题

大部分情况下,你可以使用React.PureComponent而不必写你自己的shouldComponentUpdate,它只做一个浅比较。但是由于浅比较会忽略属性或状态突变的情况,此时你不能使用它。

class ListOfWords extends React.PureComponent {
 render() {
  return <div>{this.props.words.join(',')}</div>;
 }
}

class WordAdder extends React.Component {
 constructor(props) {
  super(props);
  this.state = {
   words: ['marklar']
  };
  this.handleClick = this.handleClick.bind(this);
 }

 handleClick() {
  // This section is bad style and causes a bug
  const words = this.state.words;
  words.push('marklar');
  this.setState({words: words});
 }

 render() {
  return (
   <div>
    <button onClick={this.handleClick} />
    <ListOfWords words={this.state.words} />
   </div>
  );
 }
}

在ListOfWords中,this.props.words是WordAdder中传入的其state的一个引用。虽然在WordAdder的handelClick方法中被改变了,但是对于ListOfWords来说,其引用是不变的,从而导致并没有被更新。

解决方法

在上面的问题中可以发现,当一个数据是不变数据时,可以使用一个引用。但是对于一个易变数据来说,不能使用引用的方式给到PureComponent。简单来说,就是我们在PureComponent外层来修改其使用的数据时,应该给其赋值一个新的对象或者引用,从而才能确保其能够进行重新渲染。例如上面例子中的handleClick可以通过以下几种来进行修改从而确认正确的渲染:

handleClick() {
 this.setState(prevState => ({
  words: prevState.words.concat(['marklar'])
 }));
}

或者

handleClick() {
 this.setState(prevState => ({
  words: [...prevState.words, 'marklar'],
 }));
};

或者针对对象结构:

function updateColorMap(oldObj) {
 return Object.assign({}, oldObj, {key: new value});
}

immutable.js

Immutable.js是解决这个问题的另一种方法。它通过结构共享提供不可突变的,持久的集合:

  • 不可突变:一旦创建,集合就不能在另一个时间点改变。
  • 持久性:可以使用原始集合和一个突变来创建新的集合。原始集合在新集合创建后仍然可用。
  • 结构共享:新集合尽可能多的使用原始集合的结构来创建,以便将复制操作降至最少从而提升性能。
// 常见的js处理
const x = { foo: 'bar' };
const y = x;
y.foo = 'baz';
x === y; // true

// 使用 immutable.js

const SomeRecord = Immutable.Record({ foo: null });
const x = new SomeRecord({ foo: 'bar' });
const y = x.set('foo', 'baz');
x === y; // false

总结

PureComponent 真正起作用的,只是在一些纯展示组件上,复杂组件使用的话shallowEqual 那一关基本就过不了。另外在使用的过程中为了确保能够正确的渲染,记得 props 和 state 不能使用同一个引用哦。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 当前日期转化为中文的实现代码
May 13 Javascript
firefox下jQuery UI Autocomplete 1.8.*中文输入修正方法
Sep 19 Javascript
QQ空间顶部折页撕开效果示例代码
Jun 15 Javascript
Javascript基于对象三大特性(封装性、继承性、多态性)
Jan 04 Javascript
javascript先序遍历DOM树的方法
Feb 27 Javascript
在线引用最新jquery文件的实现方法
Aug 26 Javascript
fullCalendar中文API官方文档
Feb 07 Javascript
JS实现unicode和UTF-8之间的互相转换互转
Jul 05 Javascript
JavaScript通过mouseover()实现图片变大效果的示例
Dec 20 Javascript
小程序实现自定义导航栏适配完美版
Apr 02 Javascript
vue实现移动端轻量日期组件不依赖第三方库的方法
Apr 28 Javascript
vue使用axios实现excel文件下载的功能
Jul 16 Javascript
详解在React.js中使用PureComponent的重要性和使用方式
Jul 10 #Javascript
echarts整合多个类似option的方法实例
Jul 10 #Javascript
详解使用Next.js构建服务端渲染应用
Jul 10 #Javascript
node.js中TCP Socket多进程间的消息推送示例详解
Jul 10 #Javascript
vue中$set的使用(结合在实际应用中遇到的坑)
Jul 10 #Javascript
JavaScript中 ES6变量的结构赋值
Jul 10 #Javascript
vue超时计算的组件实例代码
Jul 09 #Javascript
You might like
PHP详细彻底学习Smarty
2008/03/27 PHP
PHP操作MongoDB时的整数问题及对策说明
2011/05/02 PHP
PHP获取当前日期和时间及格式化方法参数
2015/05/11 PHP
THINKPHP截取中文字符串函数实例代码
2017/03/20 PHP
PHP实现的文件浏览器功能简单示例
2019/09/12 PHP
javascript 尚未实现错误解决办法
2008/11/27 Javascript
IE event.srcElement和FF event.target 功能比较
2010/03/01 Javascript
IE8下关于querySelectorAll()的问题
2010/05/13 Javascript
基于JavaScript 数据类型之Boolean类型分析介绍
2013/04/19 Javascript
jQuery 事件的命名空间简单了解
2013/11/22 Javascript
js与jQuery 获取父窗、子窗的iframe
2013/12/20 Javascript
关于页面嵌入swf覆盖div层的问题的解决方法
2014/02/11 Javascript
Nodejs中读取中文文件编码问题、发送邮件和定时任务实例
2015/01/01 NodeJs
Bootstrap编写一个在当前网页弹出可关闭的对话框 非弹窗
2016/06/30 Javascript
js实现上传并压缩图片效果
2018/01/10 Javascript
详解关于vue-area-linkage走过的坑
2018/06/27 Javascript
用Object.prototype.toString.call(obj)检测对象类型原因分析
2018/10/11 Javascript
使用python爬取B站千万级数据
2018/06/08 Python
有关Python的22个编程技巧
2018/08/29 Python
对numpy中二进制格式的数据存储与读取方法详解
2018/11/01 Python
Python实现合并两个有序链表的方法示例
2019/01/31 Python
TensorFlow索引与切片的实现方法
2019/11/20 Python
适合Python初学者的一些编程技巧
2020/02/12 Python
Python数据结构dict常用操作代码实例
2020/03/12 Python
Python私有属性私有方法应用实例解析
2020/09/15 Python
Window10上Tensorflow的安装(CPU和GPU版本)
2020/12/15 Python
python爬虫如何解决图片验证码
2021/02/14 Python
html5 input属性使用示例
2013/06/28 HTML / CSS
BudgetAir印度:预订航班、酒店和汽车租赁
2019/07/07 全球购物
台湾全方位线上课程与职能学习平台:TibaMe
2019/12/04 全球购物
职员竞岗演讲稿
2014/05/14 职场文书
社区文艺活动方案
2014/08/19 职场文书
简单的辞职信模板
2015/05/12 职场文书
nginx网站服务如何配置防盗链(推荐)
2021/03/31 Servers
自动在Windows中运行Python脚本并定时触发功能实现
2021/09/04 Python
MySQL中IO问题的深入分析与优化
2022/04/02 MySQL