可能有人问,为啥会突然讲这么基础的内容? 原因是这样的,最近工作实在太忙,没有时间看更难理解的内容,所以我想回到开始的章节,整理一下基础内容,谁说基础内容就没有含金量?看完后,我还是有收获的
JSX 是什么?
回答这个问题前,我们先来看下面这个问题: 在老版本的 React 中,为什么写 JSX 的文件要默认引入 React?
比如:
import React from react
function Index(){return <div> hello,React </div>}
因为 JSX 在被 Babel 编译后,JSX 标签结构会变成 React.createElement 形式,所以需要引入React,防止找不到 React 引起报错。
了解React.createElement
前面讲到JSX语法里 闭合标签元素会被 React.createElement 处理, 看一下这个 API 的用法。
React.createElement(
type,
[props],
[...children])
createElement 参数:
-
第一个参数 type:如果是组件类型,会传入组件对应的类或函数; 如果是 DOM 元素类型,则传入 div 或者 span 之类的字符串。
-
第二个参数 props:一个对象在 DOM 类型中为标签属性,在组件类型中为 props。
-
其他参数 Children:依次为该元素的子元素,根据顺序排列。
-
返回结果: React Element对象。
举个例子:
<div>
<TextComponent />
<div>hello,world</div>
let us learn React!
</div>
上面的代码会被 Babel 先编译成:
React.createElement(
"div", null,
React.createElement(TextComponent, null),
React.createElement("div", null, "hello,world"),
"let us learn React!"
)
ReactElement 对象
由上述内容可知,ReactElement 对象是通过 React.createElement 创建出来的特殊对象。 它大致长这个样子
const element = {
$$typeof: REACT_ELEMENT_TYPE, // Element 元素类型
type: type, // type 属性,证明是元素还是组件
key: key, // key属性
ref: ref, // ref属性
props: props, // props属性
...
};
createElement 原理揭秘
export function createElement(type, config, children) {
/* 初始化参数*/
const props = {};
let key = null,propName, ref = null, self = null, source = null;
if (config != null) { /* 处理ref */
if (hasValidRef(config)) {
ref = config.ref;
}
if (hasValidKey(config)) { /* 处理key */
key = '' + config.key;
}
for (propName in config) { /*处理props */
if (
hasOwnProperty.call(config, propName) &&
! RESERVED_PROPS.hasOwnProperty(propName))
{props[propName]= config[propName];}
}
}
/* 处理Children逻辑*/
const childrenLength = arguments.length - 2;
if (childrenLength === 1) { // 只有一个 Children 的情况
props.children = children;
} else if (childrenLength > 1) {
// 存在多个 Children 的情况
const childArray = Array(childrenLength);
for (let i = 0; i < childrenLength; i++) {
childArray[i]= arguments[i + 2];
}
props.children = childArray;
}
/* 省略处理 defaultProps */
return ReactElement(type,key,ref,self,source,
ReactCurrentOwner.current,props,);
}
createElement 做的事情大致可以分为:
- 初始化参数,比如 props、key、ref 等。
- 单独处理 key 和 ref 属性,处理 props 里面的其他属性。
- 形成 Children 结构的数组。
- 通过 ReactElement 创建 Element 对象并返回。
const ReactElement = function(type, key, ref, self, source,
owner, props) {
const element = {
$$typeof: REACT_ELEMENT_TYPE,
type: type,
key: key,
ref: ref,
props: props,
_owner: owner,
};
/* 创建element对象*/
return element;
};
ReactElement 作为一个纯函数,做的事情很简单,就是根据传进来的参数,创建并返回一个 Element对象。
好了,相信看完这些,我们对JSX和 createElement 有了一些原理上的认知,这些应该都是后面学习fiber结构的基础,所以 温故知新都必不可少呢,下期见