React提供了React.createClass函数,用于生成React Component构造函数。构造函数可以生成复合型的React Component,可以带内部state。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
React.createClass = function (spec) {

var Constructor = identity(function (props, context, updater) {

// 1.绑定需要自动绑在component上的方法
if (this.__reactAutoBindPairs.length) {
bindAutoBindMethods(this);
}

// 2.初始化props,context,refs,updater
this.props = props;
this.context = context;
this.refs = emptyObject;
this.updater = updater || ReactNoopUpdateQueue;

// 3.初始化state
this.state = null;
var initialState = this.getInitialState ? this.getInitialState() : null;
this.state = initialState;
});
// 4.合入基本方法:spec的接口方法,内部方法setState,isReactComponent,forceUpdate等
Constructor.prototype = new ReactClassComponent();
Constructor.prototype.constructor = Constructor;
Constructor.prototype.__reactAutoBindPairs = [];

// 5.合入通过inject进来的spec方法,
injectedMixins.forEach(mixSpecIntoComponent.bind(null, Constructor));

// 6.合入通过参数传进来的spec方法
mixSpecIntoComponent(Constructor, spec);

// 7.获取默认props值
if (Constructor.getDefaultProps) {
Constructor.defaultProps = Constructor.getDefaultProps();
}

// 8.补充Class接口函数,设置为默认值null
for (var methodName in ReactClassInterface) {
if (!Constructor.prototype[methodName]) {
Constructor.prototype[methodName] = null;
}
}

return Constructor;
}

其中,spec是一个对象,可以提供创建构造函数需要的方法,其中render是必须存在的方法。具体可参考
React学习之React Component的详细说明和生命周期

bindAutoBindMethods方法的实现很简单,就是将__reactAutoBindPairs中的键值对方法帮到component上

1
2
3
4
5
6
7
8
9
10
11
12
13
function bindAutoBindMethods(component) {
var pairs = component.__reactAutoBindPairs;
for (var i = 0; i < pairs.length; i += 2) {
var autoBindKey = pairs[i];
var method = pairs[i + 1];
component[autoBindKey] = bindAutoBindMethod(component, method);
}
}

function bindAutoBindMethod(component, method) {
var boundMethod = method.bind(component);
return boundMethod;
}

mixSpecIntoComponent()方法主要是将spec中的方法混入组件constructor的prototype中去,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
function mixSpecIntoComponent(Constructor, spec) {
if (!spec) {
return;
}

var proto = Constructor.prototype;
var autoBindPairs = proto.__reactAutoBindPairs;

// 1.合并minxins中的spec
// MIXINS_KEY = 'mixins'
// RESERVED_SPEC_KEYS:displayName,mixins,childContextTypes,contextTypes,getDefaultProps,propTypes,statics,autobind
if (spec.hasOwnProperty(MIXINS_KEY)) {
RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins);
}

for (var name in spec) {
if (!spec.hasOwnProperty(name)) {
continue;
}

if (name === MIXINS_KEY) {
continue;
}

var property = spec[name];
var isAlreadyDefined = proto.hasOwnProperty(name);

// 2.合并spec中的静态属性和方法
if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
RESERVED_SPEC_KEYS[name](Constructor, property);
} else {

// 3.筛选需要绑定constructor上下文的

// 满足如下条件的方法需要绑定construtor上下文
// 1.ReactClassInterface中的方法
// 2.mixin混入的方法
var isReactClassMethod = ReactClassInterface.hasOwnProperty(name);
var isFunction = typeof property === 'function';
var shouldAutoBind = isFunction && !isReactClassMethod && !isAlreadyDefined && spec.autobind !== false;

if (shouldAutoBind) {
autoBindPairs.push(name, property);
proto[name] = property;
} else {

// 4.多种方式合并spec中的方法
if (isAlreadyDefined) {
var specPolicy = ReactClassInterface[name];

if (specPolicy === 'DEFINE_MANY_MERGED') {
// 定义合并方法,方法将产出合并后的执行结果
proto[name] = createMergedResultFunction(proto[name], property);
} else if (specPolicy === 'DEFINE_MANY') {
// 顺序执行方法
proto[name] = createChainedFunction(proto[name], property);
}
} else {
// 直接覆盖方法
proto[name] = property;
}
}
}
}
}