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
}
完
如有错误,请指正,欢迎评论交流,关注我,只写干货