理解JSX 和虚拟 DOM

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解JSX 和虚拟 DOM相关的知识,希望对你有一定的参考价值。

参考技术A

jsx和虚拟dom一直都是react面试中老生常谈的问题,但面试题背归背,只有把问题弄懂了才能转换成自己的真正的实力。

JSX 是一个 javascript 的语法扩展,在react项目中可以像这样声明一个变量。

所以JSX其实是React.createElement()的语法糖,JSX在编译时会被Babel编译为React.createElement方法。

这也是为什么在每个使用JSX的JS文件中,你必须显式的声明

不过,React 17 在 React 的 package 中引入了两个新入口,这些入口只会被 Babel 和 TypeScript 等编译器使用。新的 JSX 转换不会将 JSX 转换为React.createElement,而是自动从 React 的 package 中引入新的入口函数并调用。

React.createElement内部会调用ReactElement函数最后返回一个对象。

ReactElement最终会返回一个包含组件数据的js对象,这就是经常说的虚拟dom对象,也是一个react元素,其中$$typeof属性被赋值为REACT_ELEMENT_TYPE的常量标记这个对象是一个合法的react元素。

并且react提供了全局API用于校验对象是否为合法的react元素

$$typeof 属性也起到了防止 XSS 攻击的作用。
如果服务器允许用户储存任意的 JSON 数据的情况下。那么就可以手动构建 React Element 对象传入到元素中。例如:

REACT_ELEMENT_TYPE值的定义

使用 Symbol 类型是因为 JSON 中无法传递 Symbol。React 会检查 element.$$typeof 然后拒绝处理非法的元素,这样就可以规避这个问题。

使用class component或者function component的时候component都会被当作React.createElement函数中的第一个参数type传入

注意点
如果自定义组件的命名不是大写开头的话,babel只会转换成普通的标签,也称为HostComponent.

结果type会变成"funcComp"而不是funcComp组件,这也是react自定义组件为什么要大写开头的原因。

从上面的内容我们可以发现,JSX是一种描述当前组件内容的数据结构,他不包含组件schedule、reconcile、render所需的相关信息。

比如如下信息就不包括在JSX中:

所以,在组件mount时,Reconciler根据JSX描述的组件内容生成组件对应的Fiber节点。

在update时,Reconciler将JSX与Fiber节点保存的数据对比,生成组件对应的Fiber节点,并根据对比结果为Fiber节点打上标记。

以上是关于理解JSX 和虚拟 DOM的主要内容,如果未能解决你的问题,请参考以下文章

React入门-JSX和虚拟dom

React 与 虚拟DOM

谈谈对虚拟DOM的理解

深度思考 jsx虚拟 dom

虚拟DOM知多少

虚拟 DOM 到底是什么?