vue 虚拟DOM的原理

 更新时间:2020年10月03日 10:19:48   作者:guo&qi  
这篇文章主要介绍了vue 虚拟DOM的原理,帮助大家更好的理解和学习vue,感兴趣的朋友可以了解下

为什么需要虚拟DOM?

  如果对前端工作进行抽象的话,主要就是维护状态和更新视图,而更新视图和维护状态都需要DOM操作。其实近年来,前端的框架主要发展方向就是解放DOM操作的复杂性。

  运行js的速度是很快的,大量的操作DOM就会很慢,时常在更新数据后会重新渲染页面,这样造成在没有改变数据的地方也重新渲染了DOM 节点,这样就造成了很大程度上的资源浪费。

  在jQuery出现以前,我们直接操作DOM结构,这种方法复杂度高,兼容性也较差。有了jQuery强大的选择器以及高度封装的API,我们可以更方便的操作DOM,jQuery帮我们处理兼容性问题,同时也使DOM操作变得简单。

  但是聪明的程序员不可能满足于此,各种MVVM框架应运而生,有angularJS、avalon、vue.js等,MVVM使用数据双向绑定,使得我们完全不需要操作DOM了,更新了状态,视图会自动更新。更新了视图数据状态也会自动更新,可以说MVVM使得前端的开发效率大幅提升。但是其大量的事件绑定使得其在复杂场景下的执行性能堪忧,有没有一种兼顾开发效率和执行效率的方案呢?由此引入Virtual DOM(虚拟DOM)。

  利用在内存中生成与真实DOM与之对应的数据结构,这个在内存中生成的结构称之为虚拟DOM 。

  当数据发生变化时,能够智能地计算出重新渲染组件的最小代价并应用到DOM操作上。

Virtual DOM 算法

  所谓的 Virtual DOM 算法。包括几个步骤:

  1.用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中;

  2.当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异;

  3.把2所记录的差异应用到步骤1所构建的真正的DOM树上,视图就更新了。

  Virtual DOM 本质上就是在 JS 和 DOM 之间做了一个缓存。可以类比 CPU 和硬盘,既然硬盘这么慢,我们就在它们之间加个缓存。

  既然 DOM 这么慢,我们就在它们 JS 和 DOM 之间加个缓存。CPU(JS)只操作内存(Virtual DOM),最后的时候再把变更写入硬盘(DOM)。

  所谓的virtual dom,也就是虚拟节点。它通过js的Object对象模拟DOM中的节点,然后再通过特定的render方法将其渲染成真实的DOM节点 dom。diff 则是通过JS层面的计算,返回一个patch对象,即补丁对象,在通过特定的操作解析patch对象,完成页面的重新渲染。

比较两棵虚拟DOM树的差异

  比较两棵DOM树的差异是 Virtual DOM 算法最核心的部分,这也是所谓的 Virtual DOM 的 diff 算法。

  两个树的完全的 diff 算法是一个时间复杂度为 O(n^3) 的问题。但是在前端当中,你很少会跨越层级地移动DOM元素。所以 Virtual DOM 只会对同一个层级的元素进行对比:

  上面的div只会和同一层级的div对比,第二层级的只会跟第二层级对比。这样算法复杂度就可以达到 O(n)。

  在实际的代码中,会对新旧两棵树进行一个深度优先的遍历,这样每个节点都会有一个唯一的标记,如下图所示:

Virtual DOM 算法实现

  Virtual DOM 算法得实现主要是用三个函数:element,diff,patch。然后就可以实际的进行使用,如下面代码所示:

// 1. 构建虚拟DOM
var tree = el('div', {'id': 'container'}, [
  el('h1', {style: 'color: blue'}, ['simple virtal dom']),
  el('p', ['Hello, virtual-dom']),
  el('ul', [el('li')])
])

// 2. 通过虚拟DOM构建真正的DOM
var root = tree.render()
document.body.appendChild(root)

// 3. 生成新的虚拟DOM
var newTree = el('div', {'id': 'container'}, [
  el('h1', {style: 'color: red'}, ['simple virtal dom']),
  el('p', ['Hello, virtual-dom']),
  el('ul', [el('li'), el('li')])
])

// 4. 比较两棵虚拟DOM树的不同
var patches = diff(tree, newTree)

// 5. 在真正的DOM元素上应用变更
patch(root, patches)

diff算法

用 三大策略 将O(n^3)复杂度 转化为 O(n)复杂度

  • 策略一(tree diff):

  Web UI中DOM节点跨层级的移动操作特别少,可以忽略不计。

  • 策略二(component diff):

  拥有相同类的两个组件 生成相似的树形结构,
  拥有不同类的两个组件 生成不同的树形结构。

  • 策略三(element diff):

  对于同一层级的一组子节点,通过唯一id区分。

tree diff

(1)通过updateDepth对Virtual DOM树进行层级控制。
(2)对树分层比较,两棵树只对同一层次节点进行比较。如果该节点不存在时,则该节点及其子节点会被完全删除,不会再进一步比较。
(3)只需遍历一次,就能完成整棵DOM树的比较。

  diff只简单考虑同层级的节点位置变换,如果是跨层级的话,只有创建节点和删除节点的操作。

如上图所示,以A为根节点的整棵树会被重新创建,而不是移动,因此官方建议不要进行DOM节点跨层级操作,可以通过CSS隐藏、显示节点,而不是真正地移除、添加DOM节点。

以上就是vue 虚拟DOM的原理的详细内容,更多关于vue 虚拟DOM的资料请关注脚本之家其它相关文章!

相关文章

  • vue-router 基于后端permissions动态生成导航菜单的示例代码

    vue-router 基于后端permissions动态生成导航菜单的示例代码

    本文主要介绍了vue-router 基于后端permissions动态生成导航菜单的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • vue使用monaco editor汉化右键菜单示例

    vue使用monaco editor汉化右键菜单示例

    这篇文章主要为大家介绍了vue使用 monaco editor 汉化右键菜单实现汉化示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • van-uploader保存文件到后端回显后端接口返回的数据

    van-uploader保存文件到后端回显后端接口返回的数据

    前端开发想省时间就是要找框架呀,下面这篇文章主要给大家介绍了关于van-uploader保存文件到后端回显后端接口返回的数据,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-06-06
  • vue使用el-table筛选tree树形结构的数据问题

    vue使用el-table筛选tree树形结构的数据问题

    这篇文章主要介绍了vue使用el-table筛选tree树形结构的数据问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • vue3搭配pinia的踩坑实战记录

    vue3搭配pinia的踩坑实战记录

    Pinia是一个同时支持Vue2和Vue3的应用状态管理工具,简单来说就是为了管理整个应用中的响应式数据,解决各个组件交互时数据状态的不好管理的问题,下面这篇文章主要给大家介绍了关于vue3搭配pinia踩坑的相关资料,需要的朋友可以参考下
    2022-04-04
  • VUE3引入html文件并传值方法举例

    VUE3引入html文件并传值方法举例

    这篇文章主要给大家介绍了关于VUE3引入html文件并传值的相关资料,这是最近在项目中遇到了的一个需求,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-07-07
  • 详解vue-Resource(与后端数据交互)

    详解vue-Resource(与后端数据交互)

    本篇文章主要介绍了vue-Resource(与后端数据交互),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • vue嵌入第三方页面几种常见方法

    vue嵌入第三方页面几种常见方法

    在Vue中嵌入第三方页面可以采用多种方法,例如使用<iframe>、Vue插件、动态加载第三方脚本或WebComponents,不同方法适用于不同类型的内容和项目需求,如<iframe>适用于整个网页,而动态脚本和WebComponents适合特定功能,选择合适的方法可以有效整合外部资源
    2024-09-09
  • Vue实现省市区三级联动

    Vue实现省市区三级联动

    这篇文章主要为大家详细介绍了Vue实现省市区三级联动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • vue新建项目并配置标准路由过程解析

    vue新建项目并配置标准路由过程解析

    这篇文章主要介绍了vue新建项目并配置标准路由过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12

最新评论