前文中,我们完成了一个最简单的一个样例Hello react,在该样例中我们直接用jsx来创建了一个虚拟DOM,并且将这个虚拟DOM复制给了一个变量。这节课我们来继续往下学习,除了上节课中的方法还有没有其他方法来创建虚拟DOM呢?

看这节课的标题就知道肯定是有其他方法来创建虚拟DOM的,接下来我们来逐步探讨一下。

jsx来直接创建虚拟DOM

之前在看到用jsx直接创建虚拟DOM可能大家都在疑惑下面这行代码

const VDOM = <h1>Hello, react</h1>

为什么赋给VDOM常亮的不是个字符串,而是一个像HTML的标签元素呢?

这其实就是jsx的语法规则,因为这是要创建一个虚拟DOM而不是声明一个字符串类型的常量。

那么接下来就引出这样一个问题:为什么要这么写?

为什么要使用jsx语法

我们知道react官方要求我们使用jsx语法来完成相应的程序编写。但是为什么呢?我们会回顾一下之前的案例。

依然还是展示Hello, react,经过渲染后得到的的HTML元素如下:

image-20211209210013611

从图中我们可以看出,元素中和之前不同的地方就是这里的<h1>标签中有一个id属性叫title

jsx语法创建

如果我们用jsx来创建虚拟DOM的话那么和之前我们的样例里面几乎是没有区别的。只不过创建虚拟DOM这一行要稍微变动一下,要在<h1>标签中添加一个id属性,具体如下:

const VDOM = <h1 id="title">Hello, react</h1>

就简单的这一行就可以完成一个虚拟DOM的创建。

不使用jsxJavaScript语法创建

但是如果说我们对jsx语法表示疑惑,一定要用原生的js语法来创建的话也行。简单来说分以下几个步骤:

  1. 创建容器
  2. 因为还是使用react所以要引入react核心库
  3. 因为要从虚拟DOM映射到真实DOM所以要在引入react库之后引入react-dom
  4. 因为不使用jsx语法,所以不用引入babel
  5. 编写相应js代码

但是如何用原生的js语法来创建react的虚拟DOM呢?

和操作真实DOM类似,原生的JavaScript中带有createElement方法用于创建DOM节点,而react也同样拥有createElement方法来创建虚拟DOM

  • reactcreateElement方法需要接收三个参数
  • 参数一为DOM节点的标签名
  • 参数二为DOM节点的标签属性
  • 参数三为DOM节点标签体内容

知道了以上几个要点,那就好办了我们则可以直接调用React.createElement("h1", {id: "title"}, "Hello, react")来创建一个虚拟DOM。然后我们在用ReactDOM来渲染成真实DOM即可完成页面展示.代码如下:

<!-- test1.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Hello react</title>
</head>
<body>
<!--准备好一个初始容器-->
<div id="test"></div>
<!--引入react核心库-->
<script type="text/javascript" src="js/react.development.js"></script>
<!--引入react-dom库以支持react操作DOM-->
<script type="text/javascript" src="js/react-dom.development.js"></script>

<script type="text/javascript">
    const VDOM = React.createElement("h1", {id: "title"}, "Hello, react");
    ReactDOM.render(
        VDOM,
        document.getElementById("test")
    );
</script>
</body>
</html>

从以上来看如果用原生的js语法好像和jsx语法创建的虚拟DOM效果上没有什么区别啊,而且原生js语法我们更加熟悉,为什么还要使用jsx语法呢?

复杂需求两种方法对比

那么好接下来我们把需求变更一下,比如我们想要的元素如下图所示:

image-20211209213532667

图中我们看见其实也没有什么太大的变化,只是在<h1>标签中又套了一层<span>标签。那么这个需求该怎么来编写呢?

  1. 如果直接用jsx语法的话很简单,就像普通的HTML一样直接在<h1>标签里面嵌套<span>标签就行了。
const VDOM = <h1 id="tltle"><span>Hello, react</span></h1>
  1. 如果使用原生的js语法的话应该怎么写呢?
// 错误写法
const VODM = React.createElement("h1", {id: "title"}, "<span>Hello, react</span>")
// 这样写的话页面展示的时候<span>标签是不生效的。
// 因为第三个参数是标签内容,如果用引号括起来,引号中的<span>标签就成了字符串的一部分,而不是正常的 HTML 标签
// 那么应该怎么写才对呢?既然第三个参数是标签内容,如果内容中还想有标签,那就得用标签作为参数传进来才对啊
// 所以正确的写法如下。
// 正确写法
const VDOM = React.createElement(
  "h1", 
  {id: "title"}, 
  React.createElement("span", {}, "Hello, react")
)

综上所述,如果在这种多层复杂标签原生嵌套的情况下用原生js语法来创建虚拟DOM的话,那么就得使用多层的createElement方法进行多层复杂的嵌套调用,代码逻辑复杂,冗长,健壮性,可读性以及可维护性都会很低。

但是如果使用jsx的话则可以很方便地简洁明了地编写相应的代码,能够更加方便地创建虚拟DOM

所以说日常开发中,我们都使用jsx来代替原生js语法进行开发。

但是我们之前又说了,浏览器无法识别jsx语法,需要通过babel库来转换成js语法,但是经过babel转换后的jsx最终变成了一个什么样子呢?其实babel库最终是把jsx代码转换成了用原生js语法创建虚拟DOM的那种形式,就是上文中我们所看见的那React.createElement方法的调用。

因此,我们也把jsx创建虚拟DOM的写法称为原生js语法创建虚拟DOM的一个语法糖。

总结

以上便是react创建虚拟DOM的两种方法。

  • 直接使用jsx语法创建虚拟DOM
  • 使用原生js语法来创建虚拟DOM(不需要掌握,天塌下来也用不上)
  • babel库会自动把jsx语法转换为原生js语法创建虚拟DOM,这样浏览器才能识别。
  • jsx创建虚拟DOM的方法是原生js语法创建虚拟DOM的一个语法糖
  • jsx方法创建虚拟DOM更加简洁明了,更加方便快捷

Copyright statement:The articles of this site are all original if there is no special explanation, indicate the source please when you reprint.

Link of this article:https://work.lynchow.com/article/create_vdom/