react源码解析/基础-Component-PureComponent

Component&PureComponent

ComponentPureComponent是我们工作中经常使用的两个API, 它们的源码ReactBaseClasses.js文件中, 根据文件最后一行可以知道, 这个文件只导出了ComponentPureComponent.

Component

首先, 我们来看Component:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Component(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;
// We initialize the default updater but the real one gets injected by the
// renderer.
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');
};

由此可以看出, Component其实就是定义的一个构造函数, 实例属性有props, context, refsupdater, 原型上挂载了isReactComponent对象, setState()方法和forceUpdate()方法.

PureComponent

1
2
3
4
5
6
7
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;
}

PureComponent的定义就更简单了, 只定义了实例属性, 它的原型属性是通过继承Component来实现.

继承

1
2
3
4
5
6
7
8
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;

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;

那么这个继承是怎么实现的呢, 我们先来看js实现继承的几种方案:

原型式继承

1
2
3
4
5
function object(obj) {
function F() {};
F.prototype = obj;
return new F();
}

通过一个函数的原型以另一个对象为基础来生成两个相似的对象, 从而继承传入的obj.

寄生式继承

1
2
3
4
5
function inheritPrototype(child, parent) {
const childPrototype = object(parent.prototype);
childPrototype.constructor = parent;
child.prototype = childPrototype;
}

寄生式继承可以理解为原型式继承的加强版, 通过object生成新的原型之后, 再对这个原型进行加强.

到这里基本就理解PureComponen实现继承的原理了, 其实就是通过寄生式继承来实现, ComponentDummy就是扮演了原型式继承中函数F的作用. 最后Object.assign(pureComponentPrototype, Component.prototype);官方说法是为了避免原型跳跃, 我想这种做法的好处是把原型的属性尽可能提前, 暴露在最外层原型上, 节省原型查找的时间.

不得不说, React的工程师还是很牛逼的!