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}

如有谬误,请斧正,欢送评论交换,关注我,只写干货