虚拟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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
感谢大佬
[***.8.128.20]2024年03月26日 20时44分12秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
要求输出事故报告,线上日志文件却不见了!!
2019-04-27
前端嫌弃原生Swagger界面太low,于是我给她开通了超级VIP
2019-04-27
小白都能学会的Java注解与反射机制
2019-04-27
Java高并发测试框架JCStress
2019-04-27
阿里P8大神教我yaml语法,我终于不再只是使用字符串类型了
2019-04-27
Springboot 集成 i8n,两行代码实现国际化,你不想学吗?
2019-04-27
LeetCode 每日一题「判定字符是否唯一」
2019-04-27
Oracle中wm_concat的使用
2019-04-27
国庆第四天出行归来
2019-04-27
宝宝游乐园的优化思路(r6笔记第72天)
2019-04-27
UI5_INFO_FETCH_FROM_DB
2019-04-27
SAP CRM WebClient UI的配置存储数据库表
2019-04-27
SAP C4C Mashup port bindingF4帮助对话框里的数据源
2019-04-27
SAP C4C产品主数据OData服务的ETag处理
2019-04-27
SAP C4C business object的UUID和可读性更好的ID
2019-04-27
一种JavaScript里小数的精确计算方式
2019-04-27
SAP Cloud for Customer的inscreen_dataflow处理方式
2019-04-27