指导链接:React 原理解析
1. createElement
JSX 代码会被 Babel 编译为 React.createElement:
<div id="testId">
<div id="testId2">222</div>
<div id="testId3">333</div>
</div>
// 解析成以下样子
React.createElement(
"div", // -> type
{ // -> config: 把内建的几个属性(比如 ref 和 key)剔除后丢到 props 对象
id: "testId"
}, // -> children: 大于一 会是一个数组,否则的话只是一个对象
React.createElement(
"div",
{
id: "testId2"
},
"222"
),
React.createElement(
"div",
{
id: "testId3"
},
"333"
)
);
源码 ReactElement.js 文件中:
createElement为:
export function createElement(type, config, children) {}
最后返回ReactElement
// 这就是个工厂函数,帮助我们创建 React Element 的
// 内部代码很简单,无非多了一个 $$typeof 帮助我们标识
// 这是一个 React Element
const ReactElement = function(type, key, ref, self, source, owner, props) {
const element = {
// This tag allows us to uniquely identify this as a React Element
$$typeof: REACT_ELEMENT_TYPE,
// Built-in properties that belong on the element
type: type,
key: key,
ref: ref,
props: props,
// Record the component responsible for creating this element.
_owner: owner,
};
return element;
};
通过 $$typeof 来帮助我们识别这是一个 ReactElement
export const REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7;
Symbol.for(key): 返回由给定的 key 找到的 symbol,否则就是返回新创建的 symbol。
2 . Component, PureComponent
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');
};
主要的两点分别是 refs 和 updater
setState 和 forceUpdate 都是调用了 updater 中的方法
// 以下做的都是继承功能,让 PureComponent 继承自 Component
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;
/**
* Convenience component with default shallow equality check for sCU.
*/
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);
// 通过这个变量区别下普通的 Component
pureComponentPrototype.isPureReactComponent = true;
PureComponent 继承自 Component,继承方法使用了很典型的寄生组合式。
Refs 的创建方式:
ref={el => this.el = el}
React.createRef
延伸: Refs and the DOM