jsx语法转换生成虚拟DOM

前言

  • 它的本质是什么吗?运行中它会做如何的转换?
  • jsx内部又是怎么生成了虚拟DOM?
  • 虚拟DOM又是如何挂载到真实DOM上去的?

react中的jsx语法

  • 简单的jsx语法, 就是在js中写html元素,前提是script标签必须加 type=text/babel, 否则jsx语法会报错
  • jsx 仅仅只是 React.createElement(component, props, …children) 函数的语法糖
const msg1 = <h2>哈哈哈</h2>
//在js中上面这段代码等价于下面这段react.createElement()的值
const msg2 = React.createElement("h2", null, "哈哈哈");

jsx语法在babel中会转成 React.createElement()的函数调用

注意:使用了React相关的方法一定先引入react.development.js 和react-dom.development.js这两个文件,否则会报错

<script src="../react/react.development.js"></script>
<script src="../react/react-dom.development.js"></script>

babel转换

我们先用jsx语法, 开发页面。部分html代码省略,只写核心js代码


<script src="../react/react.development.js"></script>
<script src="../react/react-dom.development.js"></script>
//babel.min文件 是将 jsx转成 React.createElement函数调用的
<script src="../react/babel.min.js"></script>
<script type='text/babel'>
// 这是jsx语法
const msg1 = 
  <div class="header">
     <h2>头部</h2>
     <div class="main">主题</div>
     <footer>这里是尾部</footer>
   </div>;
ReactDOM.render(msg1, document.getElementById("app"));
</script>

然后我们在把上面的jsx代码转成 React.createElement函数的形式

转换后的React.createElement函数调用代码到js中

<script src="../react/react.development.js"></script>
<script src="../react/react-dom.development.js"></script>
// type="text/babel" 可以去掉,babel.min.js 也可以不用了。
// 因为我们代码中没有了jsx语法了。下面的代码属于正常的js代码
<script>
const msg2 = React.createElement("div", {
    class: "header"
}, React.createElement("h2", null, "\u5934\u90E8"), React.createElement("div", {
    class: "main"
}, "\u4E3B\u9898"), React.createElement("footer", null, "\u8FD9\u91CC\u662F\u5C3E\u90E8"));
//React.reder 函数渲染到浏览器上
ReactDOM.render(msg2, document.getElementById("app"));
</script>
  • jsx语法和React.createElement函数的方法都可以得到相同的结果,渲染在页面的正是DOM也是一样的。

  • 所以我们可以得出结论:jsx 仅仅只是 React.createElement(component, props, …children) 函数的语法糖

  • 在真实开发中我们不会使用React.createElement函数的方式写代码,因为可读性太差了,代码量又多,难维护,我们更喜欢使用jsx语法来编写代码

  • React.render函数是怎样把createElement函数的返回值挂载到DOM上的呢?

虚拟DOM的创建过程

React.createElement 最终创建出来一个 ReactElement对象

在上面的React.createElement函数调用后,打印它的返回值

const msg2 = React.createElement("div", {
  class: "header"
},React.createElement("h2", null, "\u5934\u90E8"), React.createElement("div", {
    class: "main"
 }, "\u4E3B\u9898"), React.createElement("footer", null, "\u8FD9\u91CC\u662F\u5C3E\u90E8"));

console.log(msg2);
ReactDOM.render(msg2, document.getElementById("app"));
  • msg2就是一个object对象,对象的第一层是html中的最外层class等于header的div。div里面的三个子元素,放在对象中的props对象中的children数组中一一对应。如果h2标签中还有子元素,那h2对象中的props对象中的children数组又会有objectd对象,… 这将一层一层的往下套

  • React利用ReactElement对象组成了一个JavaScript的对象树

  • msg2就是调用React.createElement函数时候,通过ReactElement函数转成一个JavaScript对象树的

  • 在react源码下/packages/react/index.js文件找到了createElement函数,它是 ./src/React文件下导出的

  • 找到react文件,发现它是 ./ReactElement文件下导出的

  • 找到ReactElement文件,里面有一个createElement函数,在js中本质上就是在调用这个函数

  • 它又调用了另一个ReactElement函数

  • 这个ReactElement函数返回是一个object对象,这个对象就是我们在浏览器打印出来的那个msg2, 它就是javascript对象树

JavaScript的对象树就是大名鼎鼎的虚拟DOM

  • 有了虚拟DOM,那怎么把虚拟DOM映射到真实的DOM上呢?

  • react是通过ReactDOM.render 函数把虚拟DOM挂载到真实DOM的

//把虚拟DOM挂载到 id为app的元素中
ReactDOM.render(msg2, document.getElementById("app"));

为什么要使用虚拟DOM

  • 很难跟踪状态发生的改变:原有的开发模式,我们很难跟踪到状态发生的改变,不方便针对我们应用程序进行调试
  • 操作真实DOM性能较低:传统的开发模式会进行频繁的DOM操作,而这一的做法性能非常的低
  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值