Vue.js 2.0窥探之Virtual DOM到底是什么
什么是Virtual DOM
在现代 Web 应用程序开发中,通常会使用 JavaScript 来动态地创建、操作和更新 HTML 页面元素。然而,这种操作不够有效率,需要对整个 DOM 结构进行重新渲染处理,而且更改频繁时还可能导致页面的卡顿甚至崩溃。
为了解决这个问题,Facebook的工程师在2013年推出了 Virtual DOM 技术,它是一种将虚拟的 DOM 与实际的 DOM 结构进行比较的技术。将需要更新的内容映射到虚拟 DOM 中,虚拟 DOM 会保存所有节点的信息以及它们的层次结构,并根据这些信息生成一棵完整的DOM树。每次更新时,虚拟 DOM 会首先以最小的代价计算出需要修改的地方,然后再将这些修改应用到实际的 DOM 结构中,最终渲染页面。
Vue.js 中也有类似实现,它基于 Virtual DOM 技术将更新操作减少到最小的代价并且提高了应用程序的性能。Vue.js 的 Virtual DOM 对比曾经显示,更新性能比原生 DOM 快上许多倍,并且减少了无法避免的 bug 和异常情况。
为什么需要Virtual DOM
在 HTML 网页中,浏览器将生成一个 DOM 树来表示 HTML 页面的结构。但是,因为浏览器的设计,DOM 树很容易被 JavaScript 操作,比如常见的$$('div')获取所有 div 节点,及之后的操作。但是,虽然 JavaScript 直接操作 DOM 节点的确很方便,却容易造成大量的浪费。
举个例子,当我们需要更新一个 DOM 节点时,通常是重新生成整颗 DOM 树,再将这个节点插入到正确的位置,并删除之前的节点。这样做是非常低效的,特别是当需要大量频繁的更新时,每次都要进行繁琐而低效的 DOM 渲染,会占用大量的 CPU 时间。
因此,Virtual DOM 即通过 JavaScript 的方式,实现 DOM 结构的抽象,减少 DOM 渲染的数量和频率,提高性能。Virtual DOM 是一个轻量级的完整的JavaScript对象结构,它包含了每一个文本,DOM节点和属性,并且能够表达完整的HTML文档。在 Vue.js 编程中,Virtual DOM 是神器,所以允许我们进行快捷、便利的模板渲染和组件结构操作。
Virtual DOM 的优势
- 大大提高了性能:利用快速的比较算法,在 Virtual DOM 中构建任意的数多点的数据结构进行渲染,可以大大减少在真实 DOM 中的操作。浏览器纯粹靠 CPU 操作是太慢的,所以使用虚拟DOM可以使UI的渲染更加流畅并且效率更高。
- 避免直接操作DOM带来的风险:DOM的操作显然比数据的操作的代价要高,并且也容易出错。使用虚拟 DOM 实现,会把逻辑和渲染轻量化很多倍,简化代码的编写和移动操作。
- 个性化操作:虚拟DOM的自主和多样性,可以通过编写模板方法,自己的控件从而实现个性化的操作,比如高级筛选框,动画效果等。
Virtual DOM 的适用场景
虚拟 DOM 并不是一种适合所有情况的解决方案,它有以下两个适用场景:
- 大型单页应用程序:当应用程序的结构变得越来越庞大时,虚拟 DOM 可以在大型单页应用程序中便于管理和维护。
- 多个子级组件的应用程序:Vue 虚拟 DOM 使用了相同的 DOM 树结构,这意味着子组件与父级组件共享相同的 DOM 树,这会提高性能并减少代码的重复性。
Vue.js中的Virtual DOM应用
在Vue.js为我们提供的框架中,Virtual DOM被用作了核心部件,具体步骤是:
- 将模版编译为.Render function,输出 Virtual DOM。
- 执行.Render function,生成 Virtual DOM 对象。
- 通过.Reconciliation 算法,找到新旧对比,把需要更新的 Virtual DOM 进行更改。
- 通过 new DOM()生成新的DOM,并与旧的DOM比较,找到需要修改的DOM。
- 判断修改来进行不同的操作,形成差异。
- 只将差异的部分更新到真实的DOM的渲染里面,达到优化的目的。
这样,在数据发生变化的时,组件先在 Virtual DOM 上更新,然后 Virtual DOM 在与真实 DOM 进行比较,只更新发生变化的部分,避免了整体重新渲染的问题。从而提升应用的性能。
示例1:使用 Vue.js 的Virtual DOM 排序动画效果
<template>
<div>
<h3>选手表</h3>
<button @click="sortRacers">排序</button>
<ul>
<li v-for="(racer, index) in racers" :key="racer.name" :style="{animationDelay: index * 100 + 'ms'}">
{{ racer.name }} : {{racer.mph}} mph
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
racers: [
{ name: 'Tina', mph: 300 },
{ name: 'John', mph: 200 },
{ name: 'Jared', mph: 500 },
{ name: 'Chris', mph: 350 },
{ name: 'Steve', mph: 150 }
]
}
},
methods: {
sortRacers() {
this.racers = this.racers.sort((a, b) => a.mph < b.mph ? 1 : -1)
}
}
}
</script>
在上面的示例中,每个列表的选手会在输入顺序后以相应速度移动到相应位置。这是通过设置CSS动画来完成的,设置每个列表项的animation-delay属性,用于创建逐渐增加的延迟效果。此处用Virtual DOM 和 Vue.js实现动画效果是理所当然。
示例2:使用Virtual DOM 和Vue.js 实现轮播图
<template>
<div>
<transition-group tag="ul" name="slide">
<li v-for="image in images" :key="image.id">
<img :src="image.url" alt="轮播图">
</li>
</transition-group>
</div>
</template>
<script>
export default {
data() {
return {
currentIndex: 0,
images: [
{ id: 1, url: 'https://picsum.photos/500/300?image=1' },
{ id: 2, url: 'https://picsum.photos/500/300?image=2' },
{ id: 3, url: 'https://picsum.photos/500/300?image=3' },
{ id: 4, url: 'https://picsum.photos/500/300?image=4' },
]
}
},
mounted() {
this.startPlay()
},
methods: {
startPlay() {
setInterval(() => {
this.currentIndex++
if (this.currentIndex >= this.images.length) {
this.currentIndex = 0
}
}, 1000)
}
}
}
</script>
<style scoped>
.slide-enter-active, .slide-leave-active {
transition: all .5s ease;
}
.slide-enter, .slide-leave-to {
opacity: 0;
transform: scale(1.1);
}
</style>
此处利用了Vue.js 的Transition 功能,来简便的制定轮播图动画效果。利用Virtual DOM,Vue.js 能够自动捕获实际 DOM 中的变化以及导致它们的数据改变,来完成轮播图实际整体的转换。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue.js 2.0窥探之Virtual DOM到底是什么? - Python技术站