首先我们得明白以下三个问题
-
JSX 的本质是什么,它和 JS 之间到底是什么关系?
JSX 是 JavaScript 的一种语法扩展,它和模板语言很接近,但是它充分具备 JavaScript 的能力。
-
为什么要用 JSX?不用会有什么后果?
JSX 语法糖允许前端开发者使用我们最为熟悉的类 HTML 标签语法来创建虚拟 DOM,在降低学习成本的同时,也提升了研发效率与研发体验。
在实际功能效果一致的前提下,JSX 代码层次分明、嵌套关系清晰;而 React.createElement 代码则给人一种非常混乱的“杂糅感”,这样的代码不仅读起来不友好,写起来也费劲。
-
JSX 背后的功能模块是什么,这个功能模块都做了哪些事情?
JSX 是 JavaScript 的一种语法扩展,它和模板语言很接近,但是它充分具备 JavaScript 的能力。
但是浏览器不能直接识别jsx,所以就需要将jsx编译为js。
Babel会将jsx编译为React.createElement调用的js代码。
createElement
createElement 有 3 个入参,这 3 个入参囊括了 React 创建一个元素所需要知道的全部信息。
- type:用于标识节点的类型。它可以是类似“h1”“div”这样的标准 HTML 标签字符串,也可以是 React 组件类型或 React fragment 类型。
- config:以对象形式传入,组件所有的属性都会以键值对的形式存储在 config 对象中。
- children:以对象形式传入,它记录的是组件标签之间嵌套的内容,也就是所谓的“子节点”“子元素”。
执行流程
- 拿到入参,处理key,ref,self,source四个参数
- 遍历config,筛选出可以提取到props里的属性
- 提取子元素,放到childArray数组
- 格式化defaultProps
- 发起ReactElement的调用
createElement 就像是开发者和 ReactElement 调用之间的一个“转换器”、一个数据处理层。它可以从开发者处接受相对简单的参数,然后将这些参数按照 ReactElement 的预期做一层格式化,最终通过调用 ReactElement 来实现元素的创建。
ReactElement
ReactElement 把传入的参数按照一定的规范,“组装”进了 element 对象里,并把它返回给了 React.createElement。
其实这ReactElement 对象实例,本质上是以 JavaScript 对象形式存在的对 DOM 的描述,也就是虚拟DOM节点。
虚拟DOM要转换成真实的DOM节点,还需要经过ReactDOM.render的处理
ReactDOM.render
入参为三个参数,
- element 需要渲染的元素(ReactElement)
- container 元素挂载的目标容器(一个真实DOM)
- [callback] 回调函数,可选参数,可以用来处理渲染结束后的逻辑