共计 2735 个字符,预计需要花费 7 分钟才能阅读完成。
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
}
完
如有谬误,请斧正,欢送评论交换,关注我,只写干货
正文完