jsx 和 fiber | 青训营笔记

46 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 14 天

JSX 介绍

当我们学习 React 时,就需要从 jsx 入手,如今 vue3 也支持了 jsx ,这也颇显 jsx 的重要性。

要弄清楚 jsx ,我们需要从下面两个方便入手:

  • 常用的 jsx 元素会被 React 处理成什么
  • jsx 的编译过程

JSX 会变成什么

先写一段 React jsx 代码:

import React from 'react'

const App = () => {
  return (
    <div>
      <h1>hello world</h1>
      <p>hello world</p>
    </div>
  )
}

export default App

首先 babel 会将 jsx 转换成 React.createElement 函数调用:

import React from 'react'

const App = () => {
  return React.createElement(
    'div',
    null,
    React.createElement('h1', null, 'hello world'),
    React.createElement('p', null, 'hello world')
  )
}

export default App

React.createElement 函数接收三个参数:

  • type:元素类型,可以是一个字符串,也可以是一个函数
  • props:元素的属性
  • children:元素的子元素

那么,createElement 又会被转换成什么呢?

上面的代码会被转换成:

import React from 'react'

const App = () => {
  return {
    $$typeof: Symbol.for('react.element'),
    type: 'div',
    key: null,
    ref: null,
    props: {
      children: [
        {
          $$typeof: Symbol.for('react.element'),
          type: 'h1',
          key: null,
          ref: null,
          props: {
            children: 'hello world'
          }
        },
        {
          $$typeof: Symbol.for('react.element'),
          type: 'p',
          key: null,
          ref: null,
          props: {
            children: 'hello world'
          }
        }
      ]
    }
  }
}

export default App

可以看到,createElement 函数返回的是一个对象,这个对象就是 React 元素。

最终,React 会将这个对象渲染成 DOM 元素。

fiber

React 16 之后,React 的渲染过程发生了很大的变化,它不再是同步渲染,而是采用了异步渲染的方式,这种方式被称为 fiber。在调和阶段, React Element 对象的每个子节点都会被转换成一个 fiber 对象,然后通过 fiber 对象的 childsiblingreturn 属性形成一个 fiber 树,最后通过 fiber 树的遍历来完成渲染。

jsx 最终会形成一个 fiber 树,fiber 有以下的对应关系:

  • child:一个由父级 fiber 指向子级 fiber 的指针
  • sibling:一个由兄弟 fiber 指向兄弟 fiber 的指针
  • return:一个由子级 fiber 指向父级 fiber 的指针

总结

jsx 会被转换成 React.createElement 函数调用,然后 React.createElement 函数会返回一个 React 元素,最终 React 会将这个 React 元素渲染成 DOM 元素。这中间涉及到了 babelReact.createElementReact 元素、fiber 等概念。