React源码学习笔记 PureComponent
-
查看react源码,在ReactBaseClasses.js中找到PureComponent
function PureComponent(props, context, updater) { this.props = props; this.context = context; this.refs = emptyObject; this.updater = updater || ReactNoopUpdateQueue; } const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy()); pureComponentPrototype.constructor = PureComponent; Object.assign(pureComponentPrototype, Component.prototype); pureComponentPrototype.isPureReactComponent = true;说明PureComponent和Component唯一的区别是多了一个静态变量isPureReactComponent
-
接着搜索isPureReactComponent,在ReactFiberClassComponent.js中找到
if (ctor.prototype && ctor.prototype.isPureReactComponent) { return ( !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) ); }说明PureComponent在更新时,会进行浅比较props和states
-
核心代码shallowEqual,是一个对象浅比较的方法
function shallowEqual(objA: mixed, objB: mixed): boolean { // 判断是否相等 if (is(objA, objB)) { return true; } // 不是对象直接返回fasle if ( typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null ) { return false; } const keysA = Object.keys(objA); const keysB = Object.keys(objB); // 先比较长度 if (keysA.length !== keysB.length) { return false; } // 再比较值 for (let i = 0; i < keysA.length; i++) { if ( !hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]]) ) { return false; } } return true; } -
注意事项
function checkShouldComponentUpdate( workInProgress, ctor, oldProps, newProps, oldState, newState, nextContext, ) { const instance = workInProgress.stateNode; if (typeof instance.shouldComponentUpdate === 'function') { let shouldUpdate = instance.shouldComponentUpdate( newProps, newState, nextContext, ); return shouldUpdate; } if (ctor.prototype && ctor.prototype.isPureReactComponent) { return ( !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) ); } return true; }说明可以通过shouldComponentUpdate覆盖自带的浅比较。