Bootstrap

从虚拟dom知识无痛深入vue与react的原理

 我们都知道像vue、react都有用到虚拟dom,那么虚拟dom到底是什么?框架为什么不直接操作真实dom而要在中间要引入虚拟dom呢?vue和react的虚拟dom又有什么异同呢?我们就从虚拟dom开始讲起,再来逐步引入讲解vue与react的部分原理及其异同,这里会顺便讲解到数据驱动视图及视图驱动数据,顺便明白MVVM、MVC这两种模式,顺便引入相关的八股文知识点,好好阅读这篇文章你会不小心一下子就明白了一大堆知识Σ(っ °Д °;)っ

所谓的虚拟dom、真实dom到底是什么?

实际上,我们在html文件里写的标签即为真实dom(能直接被浏览器解析渲染在页面呈现相应元素)。而虚拟 dom 就是一个普通的 js 对象,这个对象描述了界面的渲染内容虚拟dom与真实dom可以一一对应。如图:

//真实dom
<div id="app">
  <p class="text">木鱼</p>
</div>
//虚拟dom本质就是一个js对象,用来描述界面渲染内容,上述真实dom对应的虚拟dom结构如下:
{
  tag: 'div',
  props: {
    id: 'app'
  },
  chidren: [
    {
      tag: 'p',
      props: {
        className: 'text'
      },
      chidren: [
        '木鱼'
      ]
    }
  ]
}

虚拟dom的作用:

如果没有虚拟dom:作为通用框架,很难去预知数据跟界面之间到底是如何对应的(比如一个数据变了,框架不知道是界面哪个区域发生变动,数据是数据,界面是界面,框架能修改数据,也能通过render函数让界面重新渲染,但框架无法确定数据影响界面的具体区域),所以在没有虚拟 dom 的情况下,框架只能在数据发生变化了就直接将整个界面重新生成一次,这样没有发生变化的元素也会重新生成一遍,如此操作真实 dom 的代价就非常昂贵,会触发到浏览器的重排重绘让浏览器对整个页面所有元素都重新渲染,就会严重引发效率问题。

为了减少对真实 dom 无意义的操作,因此不得不引入虚拟 dom。当数据变化之后,由于框架无法知道数据与界面的一一对应关系,不知道界面哪个区域要更新,而全量生成真实dom导致的渲染代价较大,既然要全量生成,框架就选择全量生成虚拟 dom(虚拟dom是 js 对象,给 js 对象属性赋值修改属性值、改动对象结构,并不涉及界面,仅仅只是修改一个对象属性而已,效率自然是非常高的),然后通过跟之前的虚拟 dom 进行对比,找到有差异的虚拟dom节点,改动该虚拟节点所对应的真实 dom即可(注意前面提过虚拟dom与真实dom可以一一对应,如此,真实dom就无需全量生成渲染,框架仅需根据虚拟dom对比后的结果做对应的节点更新即可。

除了以上情况,框架引入虚拟dom还有第二个原因,就是建立了一个抽象层。特别是像 react 这种框架,它在设计之时并没有将自己定位为一个页面级别应用框架,而是把自己定位为一个 UI 库(UI 表示用户界面,而用户界面不一定是网页,也可能是移动端、桌面应用程序等,而不同平台差异很大,我们平时说的 dom 通常是指在页面应用中的,而像小程序、移动端 app、桌面应用都没有所谓的 dom),框架为了消除平台之间的差异,于是抽象了一个UI的表达方式,它使用一个普通对象(即虚拟 dom)来表达 UI 界面,然后根据不同的平台去具体生成真实的界面,即<

;