先写一个组件
<!--
首先是看一下,我们是用jsx的方式来写组件,jsx是语法糖方便我们来写React组件。而经过Babel转译之后的代码才是React本身需要用到的。
其次我们来看看 App 组件是继承 (extends)了React.Component
-->
import React from "react";
class App extends React.Component {
render() {
return <div>1233</div>;
}
}
看看 React.Component是什么
我们首先呀找到 React.Component。
先来看看 React 类。Component 是React的属性。
<!--
我们只看核心代码,看来React是合并了 ReactIsomorphic 的属性
-->
var React = {};
assign(React, ReactIsomorphic);
module.exports = React;
看看 ReactIsomorphic
var React = {
...
<!--
同样的找重点,我们找到了React.Component是 ReactComponent。
-->
Component: ReactComponent,
createElement: createElement,
cloneElement: cloneElement,
...
}
看看 ReactComponent
<!--
很简单,ReactComponent 是一个构造函数它有三个属性。
-->
function ReactComponent(props, context, updater) {
this.props = props;
this.context = context;
this.refs = emptyObject;
// 初始化一个 updater ,目前是默认值 (默认值啥也没干)。但是真正做事情的updater会被渲染器注入
this.updater = updater || ReactNoopUpdateQueue;
}
<!--
ReactComponent 的原型上定义了setState方法
-->
ReactComponent.prototype.setState = function (partialState, callback) {}
<!--
ReactComponent 的原型上定义了 forceUpdate 方法
-->
ReactComponent.prototype.forceUpdate = function (callback) {};
所有的React组件都是继承自 ReactComponent 的,所以React的组件都具有原型方法 setState 和三个属性。 setState 以后会说到,而三个属性会在接下来用到。
到此 我们知道了React的组件继承自ReactComponent,已经拥有基础的三个属性和几个原型方法。
而一个组件的核心方法是 render方法。即使一个组件什么都没有,也必须要求有一个render方法。
我们上边说过,我们目前使用jsx的写法来写React组件是语法糖,而一个 React组件的真面目如下:
你可以自己选择配置一下,babel编译React组件,看看其真面目,或者是这里有个小DEMO你可以拉下来看看 传送门
babel之后的 React组件
<!--jsx语法的React组件-->
import React from "react";
class App extends React.Component {
render() {
return <div>1233</div>;
}
}
<!--
'
babel转译后的 React组件,这里偷懒,React的版本是用了16.12.0,这样比较好配置babel。
'
-->
var _react = _interopRequireDefault(require("react"));
var App =
function (_React$Component) {
... 省略不重要的代码
<!--
'
这里会生成一个数组,数组内是我们子组件中定义的方法是以键值对来存在的。
'
-->
(0, _createClass2["default"])(App, [{
key: "render",-----------------------------(1)
value: function render() {
return _react["default"].createElement("div", null, "1233");
}
}]);
return App;
}(_react["default"].Component);
<!--
'
如上,(1)中的key 就是我们在组件中写的方法,如果我们加入别的方法,比如生命周期 componentDidMount(),这里就会多一项。value值是我们定义的方法体。我们在组件中写的是
'
render() {
return <div>1233</div>;
}
'
而实际上React处理的方式则是调用了。createElement 方法来处理 类html代码的。
'
-->
看一看 createElement 方法
ReactIsomorphic类中,我们很容易找到 createElement 方法
ReactElement 模块
'
核心是一个函数ReactElement,这个函数的作用是生成一个element返回
'
var ReactElement = function (type, key, ref, self, source, owner, props) {
var element = {
$$typeof: REACT_ELEMENT_TYPE,
type: type,
key: key,
ref: ref,
props: props,
// Record the component responsible for creating this element.
// 记录负责创建此 element 的 组件(component)
_owner: owner
};
...
return element;
};
'
模块还有一些方法,比如createElement方法就在这里。
'
ReactElement.createElement = function (type, config, children) {
'
参数:
type:是HTML标签名称或者是React的组件名,比如 div,AppComponent等
config: 是HTMl标签上的属性 className什么的
children: HTML标签的子元素,比如要显示的 字符串
'
var propName;
'
提取名称并保留起来。
主要是将config 中定义的属性 提取出来放置在 props中。
当然,将一些特殊的取出来 也就是预留的属性 RESERVED_PROPS。
'
var props = {};
var key = null;
var ref = null;
var self = null;
var source = null;
if (config != null) {
ref = config.ref === undefined ? null : config.ref;
key = config.key === undefined ? null : '' + config.key;
self = config.__self === undefined ? null : config.__self;
source = config.__source === undefined ? null : config.__source;
for (propName in config) {
if (config.hasOwnProperty(propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
props[propName] = config[propName];
}
}
}
'
Children,可能是一个或者是多个。将他们遍历一些并放在props的 children属性中
'
var childrenLength = arguments.length - 2;
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
var childArray = Array(childrenLength);
for (var i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
props.children = childArray;
}
'
如果type是一个React组件比如App之类的。那么组件本身会有一个defautProps属性定义默认的属性值。
这里会遍历 defaultProps,如果 props属性中没有,则放进去,如果已经存在了,就跳过。
'
if (type && type.defaultProps) {
var defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (typeof props[propName] === 'undefined') {
props[propName] = defaultProps[propName];
}
}
}
'
ReactCurrentOwner.current 默认是null
'
'
最后这里是调用了 ReactElement方法 我们前边说过,ReactElement方法最后会返回一个element.
'
return ReactElement(
type, key,
ref, self,
source, ReactCurrentOwner.current,
props);
};
简单的来说,React.createElement方法最后会返回一个element。
篇幅过长,不利于消化,我们另起一篇在来说说element.