前文中,我们完成了一个最简单的一个样例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
元素如下:
从图中我们可以看出,元素中和之前不同的地方就是这里的<h1>
标签中有一个id
属性叫title
。
用jsx
语法创建
如果我们用jsx
来创建虚拟DOM
的话那么和之前我们的样例里面几乎是没有区别的。只不过创建虚拟DOM
这一行要稍微变动一下,要在<h1>
标签中添加一个id
属性,具体如下:
const VDOM = <h1 id="title">Hello, react</h1>
就简单的这一行就可以完成一个虚拟DOM
的创建。
不使用jsx
以JavaScript
语法创建
但是如果说我们对jsx
语法表示疑惑,一定要用原生的js
语法来创建的话也行。简单来说分以下几个步骤:
- 创建容器
- 因为还是使用
react
所以要引入react
核心库 - 因为要从虚拟
DOM
映射到真实DOM
所以要在引入react
库之后引入react-dom
库 - 因为不使用
jsx
语法,所以不用引入babel
库 - 编写相应
js
代码
但是如何用原生的js
语法来创建react
的虚拟DOM
呢?
和操作真实DOM
类似,原生的JavaScript
中带有createElement
方法用于创建DOM
节点,而react
也同样拥有createElement
方法来创建虚拟DOM
。
react
的createElement
方法需要接收三个参数- 参数一为
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
语法呢?
复杂需求两种方法对比
那么好接下来我们把需求变更一下,比如我们想要的元素如下图所示:
图中我们看见其实也没有什么太大的变化,只是在<h1>
标签中又套了一层<span>
标签。那么这个需求该怎么来编写呢?
- 如果直接用
jsx
语法的话很简单,就像普通的HTML
一样直接在<h1>
标签里面嵌套<span>
标签就行了。
const VDOM = <h1 id="tltle"><span>Hello, react</span></h1>
- 如果使用原生的
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/