虚拟DOM
发布日期:2021-11-21 16:35:35 浏览次数:13 分类:技术文章

本文共 2133 字,大约阅读时间需要 7 分钟。

Virtual DOM 是一棵以 JavaScript 对象作为基础的树,用对象的属性来描述节点,实际上只是一层对真实 DOM 的抽象。可以通过一系列操作使这棵树映射到真实环境上。

虚拟DOM的最终目标是将虚拟节点渲染到视图上。但是如果直接使用虚拟节点覆盖旧节点的话,会有很多不必要的DOM操作

为了避免不必要的DOM操作,虚拟DOM在虚拟节点映射到视图的过程中,将虚拟节点与上一次渲染视图所使用的旧虚拟节点(oldVnode)做对比,找出真正需要更新的节点来进行DOM操作,从而避免操作其他无需改动的DOM。

核心是通过patch方法中的diff算法,找出本次DOM需要更新的节点来更新,其他的不更新

仅在同级的vnode间做diff,递归地进行同级vnode的diff,最终实现整个DOM树的更新。因为跨层级的操作是非常少的,忽略不计,这样时间复杂度就从O(n3)变成O(n)。

diff 算法包括几个步骤:

  • 用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中
  • 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异
  • 把所记录的差异应用到所构建的真正的DOM树上,视图就更新了

diff 算法的实现过程

  • patch(container,vnode) :初次渲染的时候,将VDOM渲染成真正的DOM然后插入到容器里面。
  • patch(vnode,newVnode):再次渲染的时候,将新的vnode和旧的vnode相对比,然后之间差异应用到所构建的真正的DOM树上。

1. patch(container,vnode)

通过这个函数可以让VNode渲染成真正的DOM

function createElement(vnode) {    var tag = vnode.tag  var attrs = vnode.attrs || {}    var children = vnode.children || []    if (!tag) {        return null    }    // 创建真实的 DOM 元素    var elem = document.createElement(tag)    // 属性    var attrName    for (attrName in attrs) {        if (attrs.hasOwnProperty(attrName)) {            // 给 elem 添加属性           elem.setAttribute(attrName, attrs[attrName])        }    }    // 子元素    children.forEach(function (childVnode) {        // 给 elem 添加子元素,如果还有子节点,则递归的生成子节点。        elem.appendChild(createElement(childVnode))  // 递归    })    // 返回真实的 DOM 元素    return elem}

2. patch(vnode,newVnode)

这里我们只考虑vnode与newVnode如何对比的情况:

function updateChildren(vnode, newVnode) {    var children = vnode.children || []    var newChildren = newVnode.children || []  // 遍历现有的children    children.forEach(function (childVnode, index) {        var newChildVnode = newChildren[index]  // 两者tag一样        if (childVnode.tag === newChildVnode.tag) {            // 深层次对比,递归            updateChildren(childVnode, newChildVnode)        } else {   // 两者tag不一样           replaceNode(childVnode, newChildVnode)        }    })}

 

 

其实虚拟DOM在Vue.js主要做了两件事:

提供与真实DOM节点所对应的虚拟节点vnode

将虚拟节点vnode和旧虚拟节点oldVnode进行对比,然后更新视图

优点:

1. 在不需要手动优化的情况下,可以提供不错的性能;
2. 无需手动操作DOM:只需要写好View-Model的代码逻辑,框架会根据虚拟DOM和数据双向绑定来更新视图,极大提高开发效率。
3. 跨平台:虚拟DOM本质上是JS对象,而DOM与平台强相关,相比之下虚拟DOM可以更方便的进行跨平台操作,例如服务器渲染等。

缺点:

无法进行极致优化

转载地址:https://blog.csdn.net/yyychocolate/article/details/108086328 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Vuex
下一篇:BFC

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年03月26日 20时44分12秒