如何理解虚拟DOM
假设现在您需要编写一个如下所示的表应用程序。该表可以根据不同的字段以升序或降序显示。
这个应用程序看起来很简单,您可以想到几种不同的方法来编写它。最容易想到的可能是在JavaScript代码中存储这样的数据:
varsortKey='new'//排序字段,新增、取消、净关注、累计人数varsortType=1//升序或倒序vardata=[{.},{.},{.},]//表数据
使用三个字段分别存储当前排序的字段、排序方向、表数据;然后在表格的表头添加点击事件:当用户点击特定字段时,根据上述字段存储的内容对内容进行排序。然后使用JS或jQuery操作DOM来更新页面的排序状态和表格内容。
这样做的后果是,随着应用变得越来越复杂,JS中需要维护的字段越来越多,需要监听事件并在事件回调中更新页面的DOM操作也越来越多。应用程序将变得非常难以维护。后来,人们使用了MVC和MVP架构模式,希望通过代码组织来降低维护如此复杂的应用程序的难度。但是MVC架构并不能减少你维护的状态,也不能减少你需要在页面进行状态更新的更新操作。你需要操作的DOM还是需要操作的,只是改变了位置而已。
既然状态改变时需要操作对应的DOM元素,为什么不做一些允许视图与状态绑定的东西呢。当状态改变时,视图会自动改变,因此无需手动更新页面。这就是后来人们想出MVVM模式的原因。只要在模板中声明视图组件绑定到什么状态,双向绑定引擎就会在状态更新时自动更新视图。
MVVM可以很好的降低我们状态视图维护的复杂度。但这不是唯一的方法。还有一个非常直观的方法,可以大大减少视图更新的操作:一旦状态发生变化,使用模板引擎重新渲染整个视图,然后用新视图替换旧视图。就像上表一样,当用户点击时,JS中状态仍然会更新,但是当页面更新时,不需要手动操作DOM。整个表格直接用模板引擎重新渲染,然后设置innerHTML。
当你听到这种做法时,作为一个有经验的人,你一定立刻意识到这种做法会带来很多问题。最大的问题是,这会非常慢,因为即使是很小的状态变化也必须重建整个DOM,这太划算了;如果这样做,输入和文本区域将失去原来的焦点。最终的结论是:更新局部小视图没有问题;但对于大型视图,例如当全局应用程序状态发生变化时,以及页面的许多局部视图需要更新时,这种方法不建议。
但这里你需要理解并记住这种做法,因为稍后你会发现VirtualDOM实际上就是这么做的,只是添加了一些特殊的步骤来避免改变整个DOM树。
另外需要注意的是,上面提供的方法实际上是在解决同一个问题:维护状态和更新视图。在一般应用中,如果有一个好的解决方案来处理这个问题,大部分复杂度几乎都会降低。
DOM非常慢。如果我们打印出一个简单的div元素的属性,您将看到:
而这只是第一层。真正的DOM元素非常庞大,因为标准就是这样设计的。而且操作时一定要小心,轻微的触碰就可能导致页面重新排列,这是杀死性能的罪魁祸首。
与DOM对象相比,原生JavaScript对象处理起来更快、更简单。我们可以使用JavaScript对象轻松表示DOM树上的结构和属性信息:
varelement={tagName:'ul',//节点标签名props:{//DOM属性,使用一个对象来存储键值对id:'list'},kids:[//该节点的子节点{tagName:'li',props:{class:'item'},children:['item1']},{tagName:'li',props:{class:'item'},children:['item2']},{tagName:'li',props:{class:'项目'},children:['项目3']},]}
上面对应的HTML写法是:
ulid='列表'liclass='item'项目1/liliclass='item'项目2/liliclass='item'项目3/li/ul
由于原始DOM树的信息可以用JavaScript对象来表示,反过来,你可以根据JavaScript对象所表示的树结构来构建真正的DOM树。
正如上一章提到的,状态改变——重新渲染整个视图的方式可以稍微修改一下:使用JavaScript对象来表示DOM信息和结构,当状态改变时,重新渲染这个JavaScript对象结构。当然,这是没有用的,因为真正的页面并没有改变。
但是,您可以使用新渲染的对象树与旧树进行比较,并记录两棵树之间的差异。记录的区别在于,我们需要对页面进行真实的DOM操作,然后应用到真实的DOM树上,页面就会发生变化。这样就可以做到:视图的结构确实是全新的,但最终操作DOM时只是改变了差异。
这就是所谓的VirtualDOM算法。包括几个步骤:
使用JavaScript对象结构来表示DOM树的结构;然后使用这棵树构建真实的DOM树,将其插入到文档中,并在状态发生变化时重建一棵新的对象树。然后将新树与旧树进行比较,记录两棵树之间的差异,将步骤2中记录的差异应用到步骤1中构建的真实DOM树上,视图更新虚拟DOM。本质上,它是介于JS和DOM之间。期间做了缓存。可以将其比作CPU和硬盘。由于硬盘太慢,我们会在它们之间添加缓存;由于DOM太慢,我们将在它们的JS和DOM之间添加一个缓存。CPU只操作内存,最后将变化写入硬盘。
虚拟DOM使用普通的JS对象来描述DOM对象。因为它不是真正的DOM对象,所以被称为VirtualDOM。
事实上,它只是真实DOM的一层抽象。它使用JavaScript对象作为树的基础,并使用对象的属性来描述节点。最后,这棵树可以通过一系列操作映射到真实环境。
在Javascript对象中,虚拟DOM表示为Object对象。并且它至少包含三个属性:标签名、属性和子元素对象。不同的框架对这三个属性可能有不同的名称。
创建虚拟DOM的目的是为了更好地将虚拟节点渲染到页面视图中,因此虚拟DOM对象的节点与真实DOM的属性一一对应。
vue中也使用了虚拟DOM技术。
定义真实的DOM
divid='app'pclass='p'节点内容/ph3{{foo}}/h3/div
实例化vue
constapp=newVue({el:'#app',data:{foo:'foo'}})
观察render的render,我们可以得到虚拟DOM
(函数匿名(){with(this){return_c('div',{attrs:{'id':'app'}},[_c('p',{staticClass:'p'},[_v('node内容')]),_v(''),_c('h3',[_v(_s(foo))])])}})
通过VNode,Vue可以在这棵抽象树上创建节点、删除节点、修改节点。通过diff算法,得到一些需要修改的最小单元,然后更新视图,减少了DOM操作,提高了性能。
官网:渲染函数JSX—Vue.js(vuejs.org)
Vue创建一个虚拟DOM来跟踪它如何更改真实DOM。请仔细看这行代码:
返回createElement('h1',this.blogTitle)
createElement到底会返回什么?它实际上并不是一个实际的DOM元素。它更准确的名字可能是createNodeDescription,因为它包含的信息会告诉Vue需要在页面上渲染什么样的节点,包括其子节点的描述信息。我们将这样的节点描述为“虚拟节点”,并且通常将其缩写为“VNode”。“虚拟DOM”就是我们所说的从Vue组件树构建的整个VNode树。
模板引擎没有解决跟踪状态变化的问题,因为当数据发生变化时,无法获取最后的状态,因此必须删除界面上的元素并重新创建。
它具有跨平台的优势。由于虚拟DOM是基于JavaScript对象的,不依赖于真实的平台环境,因此具有跨平台的能力,比如浏览器平台、Weex、Node等,是实现SSR、小程序等的基础。
提高渲染性能。因为DOM是一个大对象,直接操作DOM,即使是一个空的div,也会很昂贵,而且执行速度远不如我们抽象出来的Javascript对象的速度。因此,需要将大量的DOM操作移至Javascript中。使用diff算法来计算真正需要更新的节点,最大限度地减少DOM操作,从而显着提高性能。虚拟DOM的优势并不是单一的操作,而是能够在大量且频繁的数据更新下合理高效地更新视图。
diff,顾名思义,在构建DOM的过程中,diff过程就是对DOM变化进行比较和计算的地方。其核心是patch算法,它将变化映射到真实的DOM上,因此视图的创建和更新过程是这样的:
使用JavaScript对象结构来表示DOM树的结构;然后使用这棵树构建真实的DOM树,将其插入到文档中,并在状态发生变化时重建一棵新的对象树。然后将新树与旧树进行比较,记录两棵树之间的差异,并将步骤2中记录的差异应用到步骤1中构建的真实DOM树上,视图将被更新。
大家好,今天小编关注到一个比较有意思的话题,就是关于培训学校招生对象免费的问题,于是小编就整理了4个相关介绍培训学校招生对象免费的解答,让我们一起看看吧。全科教…
【Vue3】获取DOM节点的几种方式1.原生js获取DOM节点:document.querySelector(selector)document.getElem…
Web前端面试高频考点——Vue3.x新API系列文章目录内容参考链接JavaScript面试高频考点HTML、CSS、JavaScript、ES6、AJAX、…
js遍历mapjavascript怎么遍历mapvarmap=newHashMap();地图.put(a,1);地图.put(b,2);遍历:varkey=ma…
javaScript中合并对象的多种方式javaScript合并对象的多种方式:1、方式一:Object.assign(obj1,obj2,…)参数1:obj1…
2024-10-30 06:40:09
2024-10-30 04:45:43
2024-10-30 03:12:04
2024-10-30 00:51:08
2024-10-29 22:30:06
大家好,今天小编关注到一个比较有意思的话题,就是关于南京培训机构暂停多久开学的问…
大家好,今天小编关注到一个比较有意思的话题,就是关于电脑培训班开班典礼策划的问题…