PureComponent原理

1. PureComponent介绍

PureComponent会对propsstate进行浅比较,跳过不必要的更新,提高组件性能。

2. demo举例

使用Component

import React, { Component } from "react";

class Foo extends Component {
  render() {
    console.log("foo-render")
    const { num } = this.props;
    return <div>foo-{num}</div>;
  }
}
class App extends Component {
  state = {
    num: 0,
  };
  handle = () => {
    this.setState({
      num: 0,
    });
  };
  render() {
    const { num } = this.state;
    return (
      <div>
        <button onClick={this.handle}>点我</button>
        <Foo num={num} />
      </div>
    );
  }
}

点击按钮,即使num值不变,组件Foo仍然更新了,控制台打印了foo-render

使用PureComponent

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

class Foo extends PureComponent {
  render() {
    console.log("foo-render")
    const { num } = this.props;
    return <div>foo-{num}</div>;
  }
}

只有num值改变时,才会触发Foo组件render

3. 原理

react源码搜索checkShouldComponentUpdate方法可以看到下面代码,去掉dev内容

/**
 * 是否更新组件
 * @param {*} workInProgress 
 * @param {*} ctor 
 * @param {*} oldProps 
 * @param {*} newProps 
 * @param {*} oldState 
 * @param {*} newState 
 * @param {*} nextContext 
 * @returns true更新; false不更新
 */
function checkShouldComponentUpdate(
  workInProgress,
  ctor,
  oldProps,
  newProps,
  oldState,
  newState,
  nextContext,
) {
  const instance = workInProgress.stateNode;
// 组件实例上有shouldComponentUpdate方法,调用拿方法返回值
  if (typeof instance.shouldComponentUpdate === 'function') {
    let shouldUpdate = instance.shouldComponentUpdate(
      newProps,
      newState,
      nextContext,
    );
    return shouldUpdate;
  }
   // 重点在这
  // 原型上有isPureReactComponent属性,则是extends PureComponent
  // PureComponent在react源码中声明时,在原型上添加了 isPureReactComponent 属性
  // PureComponent.prototype.isPureReactComponent === true
  if (ctor.prototype && ctor.prototype.isPureReactComponent) {
    return (
     // 只对props和state浅比较
      !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)
    );
  }
  return true;
}

下面代码是isPureReactComponent来源,是react在声明PureComponent时,在原型上添加了isPureReactComponent = true的属性

function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;

function PureComponent(props, context, updater) {
  this.props = props;
  this.context = context;
  // If a component has string refs, we will assign a different object later.
  this.refs = emptyObject;
  this.updater = updater || ReactNoopUpdateQueue;
}

const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
pureComponentPrototype.constructor = PureComponent;
// Avoid an extra prototype jump for these methods.
Object.assign(pureComponentPrototype, Component.prototype);
// PureComponent原型上有个isPureReactComponent属性,用来标识是PureComponent组件
pureComponentPrototype.isPureReactComponent = true;

所以if (ctor.prototype && ctor.prototype.isPureReactComponent) {}判断是PureComponent组件,才走浅比较逻辑。

4. 浅比较原理

只作对象的每个key的引用比较,不深层遍历比较

function shallowEqual (obj1, obj2) {
  if (obj1 === obj2) { return true  }
  if (typeof obj1 !== 'object' || 
      obj1 === null || 
      typeof obj2 !== 'object' || 
      obj2 === null) 
  {
    return false 
  }
  let keys1 = Object.keys(obj1)
  let keys2 = Object.keys(obj2)
  if (keys1.length !== keys2.length) {
    return false  
  }
  for (const key of keys1) {
    if (!obj2.hasOwnProperty(key) || obj1[key] !== obj2[key]) {
      return false    
    }  
  }
  return true
}

如有错误,请指正,欢迎评论交流,关注我,只写干货

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

勇敢快乐的风筝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值