「React」问:jsx是如何转变为dom的?

210 阅读2分钟

首先我们得明白以下三个问题

  • 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] 回调函数,可选参数,可以用来处理渲染结束后的逻辑