1. PureComponent介绍
PureComponent会对props
和state
进行浅比拟,跳过不必要的更新,进步组件性能。
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}
完
如有谬误,请斧正,欢送评论交换,关注我,只写干货