React essence note - 1 - JSX
JSX 的本质是什么, 它和 JS 之间到底是什么关系?
JSX的本质JavaScript的语法扩展JSX是JavaScript的一种语法扩展,它和模板语言很接近,但是它充分具备JavaScript的能力.
JSX 语法是如何在 JavaScript 中生效的
JSX会被编译为React.createElement(),React.createElement()将返回一个叫做React Element的JS对象- 上面提到的
编译由Babel完成
什么是Babel?
Babel是一个工具链(语法转换器), 主要用于将ES2015+的代码转换为向后兼容的JavaScript语法, 以便能够运行在当前和旧版本的浏览器或者其他环境中Babel也具备将JSX语法转换为JavaScript代码的能力.
<!-- JSX -->
<div className="app">
<div class="title"> I am Title </div>
<div class="content"> I am content </div>
</div>
- 转换为
// React.createElement
"use strict";
/*#__PURE__*/
React.createElement("div", {
className: "app"
}, /*#__PURE__*/React.createElement("div", {
class: "title"
}, " I am Title "), /*#__PURE__*/React.createElement("div", {
class: "content"
}, " I am content "));
- 所有的
JSX标签都呗转化成为了React.creatElement调用. 我们写的JSX其实写的就是React.createElement,虽然看起来像HTML,但也只是“看起来像”而已. JSX的本质:React.createElement这个JavaScript调用的语法糖.(写一行JSX,就会调用React.createElement)
既然 JSX 等价于一次 React.createElement调用,什么官方不直接推荐我们用 React.createElement来创建元素呢?
- 原因很简单,
JSX代码层次分明,嵌套关系清晰 React.createElement代码则给人一种非常混乱的代码结构JSX语法糖允许前端开发者使用我们最为熟悉的类HTML标签语法来创建虚拟DOM,在降低学习成本的同时,也提升了研发效率与研发体验。
为什么要用 JSX? 不用会有什么后果?
JSX 背后的功能模块是什么, 这个功能模块都做了哪些事情?
React.createElement 工作流程
- 1: 入口 函数调用
React.createElement - 2: 二次处理
key,ref,self,source四个属性值 - 3: 遍历
config, 筛选出可以作为props的属性 - 4: 提取子元素, 推入
childArray(props.children)数组 - 5: 格式化
defaultProps - 6: 结合以上数据作为入参, 发出
React.createElement调用
createElement 中并没有十分复杂的涉及算法或者真实 DOM 的逻辑,几乎每个步骤都在格式化数据
createElement 就像是 开发者 和 ReactElement 调用之间的一个 转换器, 一个数据处理层
createElement: 开发者处接受相对简单的参数, 然后将这些参数按照 ReactElement的预期作一层格式化, 最终通过调用ReactElement实现元素的创建
createElement只是个 参数中介
ReactElement
createElement执行到最后会return一个针对ReactElement的调用
return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props)
ReactElement只做了一件事,创建,说得更精确一点,组装ReactElement把传入的参数按照一定的规范,组装进了element对象里, 并把它返回给React.createElement
const ReactElement = function(type, key, ref, self, source, owner, props) {
const element = {
// REACT_ELEMENT_TYPE是一个常量,用来标识该对象是一个ReactElement
$$typeof: REACT_ELEMENT_TYPE,
// 内置属性赋值
type: type,
key: key,
ref: ref,
props: props,
// 记录创造该元素的组件
_owner: owner,
};
//
if (__DEV__) {
// 这里是一些针对 __DEV__ 环境下的处理,对于大家理解主要逻辑意义不大,此处我直接省略掉,以免混淆视听
}
return element; // 🚀 返回给 React.createElement
}
- 最终
React.createElement又把它交回到了开发者手中。整个过程如下图所示

- 这个
ReactElement对象实例 本质上是以JavaScript对象存在的对DOM的描述,也就是虚拟DOM 虚拟DOM和真实DOM的Gap由ReactDOM.render()来填补
ReactDOM.render
ReactDOM.render(
// 需要渲染的元素(ReactElement)
element,
// 元素挂载的模板容器(一个真实DOM)
container,
// 回调函数,可选参数,用来处理渲染结束后的逻辑
[callback]
)
- 第二个参数就是一个真实的 DOM 节点,这个真实的 DOM 节点充当“容器”的角色
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
Keep learning

浙公网安备 33010602011771号