【虚拟DOM】浅析 虚拟DOM「建议收藏」

【虚拟DOM】浅析 虚拟DOM「建议收藏」虚拟DOM作为目前流行的DOM操作思想,被广泛用在react中,这套设计的确在用户体验上带来了显著提升。下面我们来浅析一下这个东西,一步步看下去,希望你能有所收获。设计理念尽管MVVM将页面逻辑实现的核心转移到数据层面的修改上,但是最终数据层反映到页面上View的层的渲染和改变仍是通过对应的指令进行DOM操作来完成的。而且,通常一次ViewModel的变化可能会触发液面上多个指令操……

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

虚拟DOM作为目前流行的DOM操作思想,被广泛用在react中,这套设计的确在用户体验上带来了显著提升。下面我们来浅析一下这个东西,一步步看下去,希望你能有所收获。

这里写图片描述
设计理念

尽管MVVM将页面逻辑实现的核心转移到数据层面的修改上,但是最终数据层反映到页面上View的层的渲染和改变仍是通过对应的指令进行DOM操作来完成的。而且,通常一次ViewModel的变化可能会触发液面上多个指令操作DOM的变化,从而造成页面结构层发生大量DOM操作或渲染。❤️ 现在关注【前端修罗场】,后台回复【666】,即可获取一份【免费的优质学习资料】,一起学习,一起进步~

例如:
这里写图片描述

当你使用MVVM时,就会生成一个列表。

现在我们把 content 变成:
[{value:0},{value:1},{value:2},{value:3}],即增加一个。
如果在MVVM中一般会重新渲染整个列表,包括列表中无须改变的部分也会重新渲染一次,例如包含值1,2,3的三个列表。

但是,你肯定会想,其实只要直接改变DOM,在<ul>子元素前插入一个新的
<li>就OK了,是不是。
但是,通常MVVM是不会这么做的。

所以,当发生大量DOM操作时,会消耗更多性能。

那问题来了,该如何改进ViewModel呢?即,如何只增加一个<li>这个问题。

这里我们需要结合“新旧比较”的思想,将新的Model data和旧的Model data对比,然后记录ViewModel的改变方式和位置,就知道这次View层应该怎样更新,这样比直接重新渲染整个列表高效。

简单而言,ViewModel里的数据就是描述页面View内容的另一种数据结构,不过需要结合特定的MVVM描述语法编译生成完整的DOM结构。那么,结合后上面的代码就变成下面这样:

这里写图片描述

此时我们需要增加一个新的<li>,按照上面的思路,就是先生成一个新的ulElement,然后与旧的ulElement进行结构上的对比,那么,其实就是在旧的ulElement对象的children属性额最前面增加一份内容,即:

{ 
   tagName:'li',
      children:[{ 
   
                 tagName:'span',
                 nodeValue:0
        },{ 
   
                 tagName:'span',
                 nodeText:'text-0'
 }]}

Jetbrains全家桶1年46,售后保障稳定

但是,你要注意它不是在旧的ulElement上增加,而是生成一个新的包含新增的ulElement
此时,你可以把这里的ulElement理解为VirtualDOM(虚拟DOM)。

虚拟DOM是什么?先来看一段定义:

VirtualDOM是一个能够直接描述一段HTML DOM结构的Javascript对象,浏览器可以根据其结构按照一定规则创建出确定唯一的HTML DOM结构。

下面我们具体讲解下虚拟DOM的核心实现思路。
这里写图片描述

实现核心思路

从上一节中,我们稍微知道了什么是虚拟DOM,用一句话总结其操作的核心可分为三步:

  1. 创建Virtual DOM;
  2. 对比两个Virtual DOM 生成差异化VirtualDOM;
  3. 将差异化Virtual DOM 渲染到页面上;

下面我们从这三个步骤分别讲起。

创建虚拟 DOM

如何创建呢?你可能会想通过遍历HTML片段创建,但是这样创建有一个问题,因为遍历HTML就意味着你要使用到DOM的读取操作,那这样的话,不是就没有多大意义了。

一个更通用的方法是,自己实现HTML字符串文本的解析方式,根据标签之间的关系,读取生成Virtual DOM结构。例如:

这里写图片描述

现在关键是createVDOM如何实现了。
我们再回头看看:
这里写图片描述
根据上图,在createVDOM的实现上,需要逐个分析字符串htmlString_ul中的字符,根据词法分析内容,将标签名字存入tagName,属性存入attributes,子标签内容存入children

这样,你就将一段HTML字符串解析成一个Javascript对象了。

到现在,有没有更深刻地体会到什么不同之处了?
这里写图片描述

我们看到,上面的方式是Javascript通过直接分析HTML字符串文本来生成VirtualDOM,而非对DOM API进行操作。

所以,小结一下,创建VirtualDOM的过程就是将一段DOM描述字符串解析成VirtualDOM对象的过程,这相当于实现了一个HTML文本解析器,但没有生成DOM对象树。故当交给浏览器解析的时候解析的不是HTML,而是Javascript对象。

但是。。还没完呢。生成了VirtualDOM后,还需要进行渲染,生成一个真实的DOM,毕竟前面的是虚拟的嘛。

来看一下如何渲染生成真实的DOM吧:

这里写图片描述

接下来,进入第二步骤。

VirtualDOM新旧对比

这里写图片描述
当发生改变时,通常会生成一个新的VirtualDOM结构来表示改变后的状态,然后进行“新旧”比较,找出差异性,得到一个差异树对象。

这里面有一个关键的地方,就是如何进行“新旧”比较。

这里用到的算法实际上是对多叉树结构的遍历算法。而该遍历算法又分为深度与广度遍历。这里我们主要以深度优先遍历算法来讲解“新旧”比较的过程。(广度优先类似)
这里写图片描述
我们先看上图,对上图进行深度优先遍历的结果:abdecfg
接着改变一下,新增一块内容,如下图红色部分:
这里写图片描述
此时,对该图进行深度优先遍历的结果:ahijbdecfg

我们把这两个图的深度优先遍历结果放在一起,如下:
这里写图片描述
现在,我们是不是能容易地分析出需要再a和b节点之间插入hij节点。然后根据hij节点的关系,可以看出节点h是i与j节点的父节点,那么我们就知道了现在只需要插入完整的h节点。
上面有提到广度优先类似,稍微看一下吧:
广度优先的遍历结果分别如下:

这里写图片描述

此时我们发现有2处是需要插入的,即需要进行2步操作,那么这就需要进一步判断来合并这2个操作。

小结一下,上面我们只是讲到了“新旧”对比,主要涉及如何发现其中改变的内容,实际上除了这些,你还需要记录发生差异化改变的类型和位置,例如是对哪一类元素进行增加\删除\替换操作等。

最后,第三步是渲染新生成的差异化虚拟DOM。

渲染新生成的差异化虚拟DOM

经过差异化比较后,你能获取到发生改变之后的“差异化VirtualDOM",”差异化类型“和”差异化位置“。
现在就很明朗了,剩下的操作就是将差异化内容经过DOM操作渲染到页面上即可完成。

总结一下,虚拟DOM最本质的区别是使用Javascript对象替代了DOM对象树,从而提升页面渲染性能。

这里写图片描述

参考:w3c

❤️ 现在关注【前端修罗场】,后台回复【666】,即可获取一份【免费的优质学习资料】,一起学习,一起进步~

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/215444.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • phpstorm怎么配置php环境_怎么配置php解释器

    phpstorm怎么配置php环境_怎么配置php解释器http://cn2.php.net/manual/zh/phpstorm安装——>next——>……下载PHP.exe地址:http://www.php.net/配置interp

  • 达梦数据库安装及配置图文教程 附DM8安装包

    达梦数据库安装及配置图文教程 附DM8安装包达梦数据库的安装欢迎使用新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML图表FLowchart流程图导出与导入导出导入欢迎使用你好!这是你第一次使用M…

  • LoadRunner11安装激活成功教程与汉化

    LoadRunner11安装激活成功教程与汉化1.安装LoadRunner的基本环境1、LoadRunner版本:LoadRunner112、电脑环境:Windows7+ie8注意:如果系统浏览器版本高于ie8,请降回ie8以下后再做LoadRunner安装。安装之前请将各种杀毒软件退出。2.安装资源1、资源:loadrunner11下载链接:https://去pan.baidu.com掉/s/1l_1k7中O8文by…

  • 经典SQL练习题(MySQL版)

    经典SQL练习题(MySQL版)原文首发于简书于[2018.07.30]网上有一篇关于SQL的经典文章,超经典SQL练习题,做完这些你的SQL就过关了,引用和分析它的人很多,于是今天复习SQL的时候找来练了练手。原作者用的是SQLServer2008,我在这里用的是MySQL8.0.11(二者语法差别不大),文本编辑器用的是Atom1.28.2(不知道大家用什么,反正用Atom写SQL确实丝质顺滑)。题目顺序…

  • 算法时间复杂度计算方式

    算法时间复杂度计算方式【对于一个给定的算法,通常要评估其正确性和运行效率的高低。算法的正确性评估不在本文范围之内,本文主要讨论从算法的时间复杂度特性去评估算法的优劣。】如何衡量一个算法的好坏呢?显然,选用的算法应该是正确的(算法的正确性不在此论述)。除此之外,通常有三个方面的考虑:(1)算法在执行过程中所消耗的时间;(2)算法在执行过程中所占资源的大小,例如,占用内存空间的大小;(3)算法的易理解性…

  • String,StringBuffer和StringBuilder的区别及使用场景[通俗易懂]

    String,StringBuffer和StringBuilder的区别及使用场景[通俗易懂]String:字符串常量。StringBuffer与StringBuilder是字符缓冲变量。StringBuffer与StringBuilder中的方法和功能完全是等价的,只是StringBuffer中的方法大都采用了synchronized关键字进行修饰,因此是线程安全的,而StringBuilder没有这个修饰,可以被认为是线程不安全的。StringBuilder是在…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号