前言
PureComponent
通过浅比较props和state来防止页面不必要的渲染,本文是原理篇,通过React源码,解读PureComponent
中浅比较规则的具体实现
版本
- react 16.6.1
结论
- render中不建议声明对象主要是为了激活
PureComponent
的渲染过滤规则,防止不必要的组件渲染 PureComponent
渲染过滤规则为:先校验state和props中的属性数量是否改变,然后用Object.is比较state和props中的属性值是否改变(用Object.is进行比较)- 如果state和props中的属性值是引用地址,每次想要触发页面渲染需要保证引用地址更新
源码解读
- 根据项目中的
ReactBaseClasses.js
可知,与component
类比较,PureComponent
组件多了isPureReactComponent
属性
/** * 以下代码摘取自“/packages/react/src/ReactBaseClasses.js,139-143行” */ const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy()); pureComponentPrototype.constructor = PureComponent; // Avoid an extra prototype jump for these methods. Object.assign(pureComponentPrototype, Component.prototype); pureComponentPrototype.isPureReactComponent = true;
- 在项目中全局搜索
isPureReactComponent
属性可查看其作用是用于比较props和state,此处全局搜索后在ReactShallowRenderer.js
中找到实现,此处意为,如果props浅比较不相等或者state浅比较不相等,则更新渲染
/** * 以下代码摘取自“/packages/react-test-renderer/src/ReactShallowRenderer.js,686-689行” */ else if (type.prototype && type.prototype.isPureReactComponent) { shouldUpdate = !shallowEqual(oldProps, props) || !shallowEqual(oldState, state); }
- 跳转到
shallowEqual
函数的实现
/** * 以下代码摘取自“/packages/shared/shallowEqual.js,全部” */ import is from './objectIs'; const hasOwnProperty = Object.prototype.hasOwnProperty; /** * Performs equality by iterating through keys on an object and returning false * when any key has values which are not strictly equal between the arguments. * Returns true when the values of all keys are strictly equal. * * 通过遍历对象上的键来执行相等性, * 当任意键的值在参数之间不严格相等时返回false, * 当所有键的值严格相等时,返回true。 */ function shallowEqual(objA: mixed, objB: mixed): boolean { if (is(objA, objB)) { return true; } 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; } // Test for A's keys different from B. 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; }
- 由以上代码可知,react浅比较(
shallowEqual
)规则为- 两个参数用
is
(方法见注释)方法判断是否相等 相等继续执行 不相等返回false - 校验是否为对象 是对象继续执行 不是对象返回false
- 校验对象属性个数是否相等 相等继续执行,不相等返回false
- 逐个遍历对象的属性,并用
is
校验是两参数中相对应的对象属性是否相等 - 下面为算法流程图:
- 两个参数用
注释
- 文中项目,指react源码项目
- 文中截取的代码只截取相关部分,不考虑语意和代码上下文
is
方法即为Objece.is
方法,判断规则如下:- 都是 undefined
- 都是 null
- 都是 true 或 false
- 都是相同长度的字符串且相同字符按相同顺序排列
- 都是相同对象(意味着每个对象有同一个引用)
- 都是数字且
- 都是 +0
- 都是 -0
- 都是 NaN
- 或都是非零而且非 NaN 且为同一个值