Component 和 PureComponent做了啥?
不知道你有没有好奇过,平时我们在写Class组件的时候,比如this.setState, this.refs是怎么来的? 为什么Class组件需要继承Component或PureComponent呢?接下来,就从源代码的层面分析一下具体的实现
Component
可以看到,Component就几个属性:
- props
- context
- refs
- updater 更新状态的关键,正常情况下不直接使用
- setState 更新状态的api, 底层调用的updater.enqueueSetState
- forceUpdate 强制更新状态的api, 底层调用的updater.enqueueForceUpdate
javascript
function Component(props, context, updater) {
this.props = props;
this.context = context;
this.refs = emptyObject;
this.updater = updater || ReactNoopUpdateQueue;
}
Component.prototype.isReactComponent = {};
Component.prototype.setState = function(partialState, callback) {
this.updater.enqueueSetState(this, partialState, callback, 'setState');
};
Component.prototype.forceUpdate = function(callback) {
this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};PureComponent
可以看到,PureComponent继承了Component组件上的原型方法,额外增加了一个isPureReactComponent 属性,在更新节点会判断此值是否是true,如果是的话,会针对state和props做一个浅比较,再决定是否重新 渲染当前组件
// TODO 将isPureReactComponent作用的地方关联上
javascript
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;
function PureComponent(props, context, updater) {
this.props = props;
this.context = context;
this.refs = emptyObject;
this.updater = updater || ReactNoopUpdateQueue;
}
// 原型继承
PureComponent.prototype = new ComponentDummy()
const pureComponentPrototype = PureComponent.prototype
pureComponentPrototype.constructor = PureComponent;
Object.assign(pureComponentPrototype, Component.prototype);
// PureComponent和Component区别的关键所在
pureComponentPrototype.isPureReactComponent = true;updater
updater做的事情就是触发react的更新,具体的过程如下:
- 从当前组件实例上拿到对应的Fiber对象
- 计算当前触发的更新的一个过期时间戳 也就是优先级的意思
- 创建一个update对象
- 将update对象添加到当前Fiber的updateQueue上
- 执行一个更新的调度
typescript
const classComponentUpdater = {
enqueueSetState(inst, payload, callback) {
// 从当前组件实例上拿到对应的Fiber对象
const fiber = getInstance(inst);
const currentTime = requestCurrentTime();
// 计算当前触发的更新的一个过期时间戳 也就是优先级的意思
const expirationTime = computeExpirationForFiber(currentTime, fiber);
// 创建一个update对象
const update = createUpdate(expirationTime);
update.payload = payload;
if (callback !== undefined && callback !== null) {
update.callback = callback;
}
// 将update对象添加到当前Fiber的updateQueue上
enqueueUpdate(fiber, update);
// 执行一个更新的调度
scheduleWork(fiber, expirationTime);
},
enqueueForceUpdate(inst, callback) {
const fiber = getInstance(inst);
const currentTime = requestCurrentTime();
const expirationTime = computeExpirationForFiber(currentTime, fiber);
const update = createUpdate(expirationTime);
// 标记当前update是一个强制更新
update.tag = ForceUpdate;
if (callback !== undefined && callback !== null) {
update.callback = callback;
}
enqueueUpdate(fiber, update);
scheduleWork(fiber, expirationTime);
},
};TIP
在实例化class组件的时候, 并没有传递updater参数, 而是在实例化之后,在立即设置updater的