const App = () => {
return App
}
//转化结果
"use strict";
var App = function App() {
return React.createElement("div", null, "App");
};
注意到的是我们的JSX最终转化成为的是React.createElement这个方法:
const App = () => {
return
span
}
"use strict";
var App = function App() {
return React.createElement(
"div",
{id: "app",key: "key"},
React.createElement("section", null,
React.createElement("img", null)
),
React.createElement("span", null, "span"));
};
当第一个参数是组件的时候,第一个参数是作为变量传入的, 可以想像的是, React.createElement内部有一个简单的判断, 如果传入的是组件的话, 内部还会调用React.createElement方法
const Child = () => {
return Child
}
const App = () => {
return
}
"use strict";
var Child = function Child() {
return React.createElement("div", null, "Child");
};
var App = function App() {
return React.createElement(
"div",
{id: "app"},
React.createElement(Child, null)); //这里
};
需要注意的是如果组件开头是一个小写的话, 会被解析成简单的字符串,在运行的时候就会报错
二. React.createElement
我们的createElement方法定义在packages/src/ReactElement.js
export function createElement(type, config, children) {
let propName;
const props = {};
let key = null;
let ref = null;
let self = null;
let source = null;
// ref和key和其他props不同, 进行单独处理
if (config != null) {
if (hasValidRef(config)) {
ref = config.ref;
}
if (hasValidKey(config)) {
key = '' + config.key;
}
self = config.__self === undefined ? null : config.__self;
source = config.__source === undefined ? null : config.__source;
//将属性名挂载到props上
for (propName in config) {
if (
hasOwnProperty.call(config, propName) &&
!RESERVED_PROPS.hasOwnProperty(propName)
) {
props[propName] = config[propName];
}
}
}
//第三个及以上的参数都被看作是子节点
const childrenLength = arguments.length - 2;
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
//当数组长度确定时,这种方式比push要节省内存
const childArray = Array(childrenLength);
for (let i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
props.children = childArray;
// merge defaultProps
if (type && type.defaultProps) {
const defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}
return ReactElement(
type,
key,
ref,
self,
source,
ReactCurrentOwner.current,
props,
);
}
ReactElement定义如下
const ReactElement = function(type, key, ref, self, source, owner, props) {
const element = {
// 每个react element的$$typeof属性都是REACT_ELEMENT_TYPE
$$typeof: REACT_ELEMENT_TYPE, // react element的内置属性
type: type,
key: key,
ref: ref,
props: props,
_owner: owner, //创建该元素的component
};
return element;
};
总的来说就是返回一个react element, 该element带有props, refs, type
和React.Component相关的文件放在react/ReactBaseClasses.js中
updater是和平台相关的,react dom 平台和react native平台setState后需要走的流程都是不一样的
function Component(props, context, updater) {
this.props = props;
this.context = context;
//初始化refs和updater,后面会被覆写
this.refs = emptyObject;
this.updater = updater || ReactNoopUpdateQueue;
}
Component.prototype.isReactComponent = {};
常用的setState方法
Component.prototype.setState = function(partialState, callback) {
invariant( //错误提醒
typeof partialState === 'object' ||
typeof partialState === 'function' ||
partialState == null,
'setState(...): takes an object of state variables to update or a ' +
'function which returns an object of state variables.',
);
//重点代码
this.updater.enqueueSetState(this, partialState, callback, 'setState');
};
Component.prototype.isReactComponent = {};
PureComponent只是实现了对Component的简单继承(详情参加<高程>一书),并且添加了isPureReactComponent属性
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;
function PureComponent(props, context, updater) {
this.props = props;
this.context = context;
this.refs = emptyObject;
this.updater = updater || ReactNoopUpdateQueue;
}
const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
pureComponentPrototype.constructor = PureComponent;
Object.assign(pureComponentPrototype, Component.prototype);
pureComponentPrototype.isPureReactComponent = true;