React PureComponent介绍与使用

前言

介绍之前可以先看下shouldComponentUpdate介绍

PureComponent介绍

React15.3中新加了一个 PureComponent 类,顾名思义, pure 是纯的意思, PureComponent 也就是纯组件,取代其前身 PureRenderMixin , PureComponent 是优化 React 应用程序最重要的方法之一,易于实施,只要把继承类从 Component 换成 PureComponent 即可,可以减少不必要的 render 操作的次数,从而提高性能,而且可以少写 shouldComponentUpdate 函数(shouldComponentUpdate通过判断props和state是否发生变化来决定需不需要重新渲染组件),主要目的就是防止不必要的子组件渲染更新。

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
 */
// 把两个对象进行浅比较
// 只比较对象的第一级
// 如果属性值是基本类型的,我们只需要比较值是否一样即可
function shallowEqual(obj1, obj2) {
	if (Object.keys(obj1).length !== Object.keys(obj2).length){
		return false;
	}
	for (let key in obj1) {
		if (obj1[key] !== obj2[key]) {
			return false;
		}
	}
	return true;
}

源码:

// 浅比较shallowEqual的源码
const hasOwn = Object.prototype.hasOwnProperty
// 这个函数实际上是Object.is()的polyfill
function is(x, y) {
  if (x === y) {
    return x !== 0 || y !== 0 || 1 / x === 1 / y
  } else {
    return x !== x && y !== y
  }
}

export default function shallowEqual(objA, objB) {
    // 首先对基本数据类型的比较
  if (is(objA, objB)) return true
 // 由于Obejct.is()可以对基本数据类型做一个精确的比较, 所以如果不等
  // 只有一种情况是误判的,那就是object,所以在判断两个对象都不是object之后,就可以返回false了
  if (typeof objA !== 'object' || objA === null ||
      typeof objB !== 'object' || objB === null) {
    return false
  }
// 过滤掉基本数据类型之后,就是对对象的比较了
  // 首先拿出key值,对key的长度进行对比
  const keysA = Object.keys(objA)
  const keysB = Object.keys(objB)
// 长度不等直接返回false
  if (keysA.length !== keysB.length) return false
  for (let i = 0; i < keysA.length; i++) {
  // key值相等的时候
  // 借用原型链上真正的 hasOwnProperty 方法,判断ObjB里面是否有A的key的key值
  // 属性的顺序不影响结果也就是{name:'daisy', age:'24'} 跟{age:'24',name:'daisy' }是一样的
  // 最后,对对象的value进行一个基本数据类型的比较,返回结果
    if (!hasOwn.call(objB, keysA[i]) ||
        !is(objA[keysA[i]], objB[keysA[i]])) {
      return false
    }
  }

  return true
}

浅比较就是只比较第一级,对于基本数据类型,只比较值;对于引用数据类型值,直接比较地址是否相同,不管里面内容变不变,只要地址一样,我们就认为没变。所以在这种情况下,我们以后用的时候,对于引用类型值修改状态或修改属性时候,对于它赋值的时候,我们尽可能把之前值拿过来克隆一份,赋给它新的地址就好~这是我们的注意点!我们想做性能优化的时候就可以在Component里做一个浅比较。

总结下就是React.PureComponent是基于浅比较,所以只要属性值是引用类型,但是修改后的值变了,但是地址不变,也不会重新渲染。在深层数据结构发生变化时可以调用 forceUpdate() 来确保组件被正确地更新。也可以用 immutable 对象加速嵌套数据的比较。

PureComponent使用(在class组件使用)

import React, { Component ,PureComponent} from 'react'

class Title extends PureComponent {
    render() {
        console.log("我是title组件")
        return (
            <div>
                标题:{this.props.title}
            </div>
        )
    }
}


class Count extends Component {
    render() {
        console.log("我是条数组件")
        return (
            <div>
                条数:{this.props.count}
            </div>
        )
    }
}

export default class Purememo extends Component {
    constructor(props){
        super(props)
        this.state={
            title:'shouldComponentUpdate使用',
            count:0
        }
    }
    componentDidMount(){
        setInterval(()=>{
            this.setState({
                count:this.state.count+1
            })
        },1000)
    }
    render() {
        return (
            <div>
                <Title title={this.state.title}></Title>
                <Count count={this.state.count}></Count>
            </div>
        )
    }
}

PureComponent与shouldComponentUpdate 共存

经过上面的简单介绍,其实可以知道如果 PureComponent 里有 shouldComponentUpdate 函数的话,直接使用 shouldComponentUpdate 的结果作为是否更新的依据,没有 shouldComponentUpdate 函数的话,才会去判断是不是 PureComponent ,是的话再去做 shallowEqual 浅比较。

// 这个变量用来控制组件是否需要更新
var shouldUpdate = true;
// inst 是组件实例
if (inst.shouldComponentUpdate) {
  shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);
} else {
  if (this._compositeType === CompositeType.PureClass) {
    shouldUpdate = !shallowEqual(prevProps, nextProps) ||
      !shallowEqual(inst.state, nextState);
  }
}

与老版本共存

import React { PureComponent, Component } from 'react';

class App extends (PureComponent || Component) {
  //...
}

注:PureComponent不可滥用,他使用在class组件内,只有那些状态和属性不经常的更新的组件我们用来做优化,对于经常更新的,这样处理后反而浪费性能,因为每一次浅比较也是要消耗时间的。

发布了82 篇原创文章 · 获赞 46 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/weixin_43720095/article/details/104940722
今日推荐