三者关系
Vue的响应式原理、双向绑定、虚拟DOM之间是一种协同工作的关系,它们共同构成了Vue框架的核心特性,用于实现数据驱动的视图更新。
-
响应式原理为基础: 响应式原理是Vue实现数据和视图关联的基础,确保数据的变化能够被观察到。
-
双向绑定建立在响应式基础上: 双向绑定通过
v-model
等指令建立在响应式系统的基础上,使得视图和数据之间能够实现双向同步。 -
虚拟DOM优化性能: 虚拟DOM作为性能优化的手段,通过比对新旧虚拟DOM,最小化对实际DOM的操作,提高了页面渲染的效率。
这三者相互协同工作,使得Vue能够高效地实现数据驱动的视图更新,同时确保了开发者能够以简洁的方式处理复杂的用户界面逻辑。
详解
1、响应式原理
数据驱动视图。数据变化,页面也跟着变化。
Vue2.x
是借助Object.defineProperty()
实现的,而Vue3.x
是借助Proxy
实现的
1、vue2.x
的Object.defineProperty()
javascript
Object.defineProperty(obj, key, {
enumerable: true,//控制属性是否会出现在对象的属性枚举中
configurable: true,//控制属性的可配置性,即是否可以使用 Object.defineProperty 修改属性的特性,是否可以删除属性。
//拦截get,当我们访问data.key时会被这个方法拦截到
get: function getter () {
//我们在这里收集依赖
return obj[key];
},
//拦截set,当我们为data.key赋值时会被这个方法拦截到
set: function setter (newVal) {
//当数据变更时,通知依赖项变更UI
}
})
Object.defineProperty
允许定义一个对象属性,其中包含 getter
和 setter
函数。getter
在每次访问属性时触发,setter
在每次修改属性时触发。
当我们通过obj.a
或obj['a']
获取属性时,getter 函数会执行,且收集到一个集合中。这样,当属性的值发生变化时,就知道哪些地方依赖于这个属性,需要进行相应的更新。
当我们给属性赋值时,setter
函数会触发。在这个函数中,我们通知之前收集的依赖进行更新,确保数据的变更能够驱动视图的变更。这样就实现了 数据驱动视图
2、vue3.x
使用的是Proxy
,与vue2.x
思想一致,
Proxy
的优势在于它提供了更强大和灵活的拦截能力,相比于 Object.defineProperty
,它可以直接代理整个对象,而不需要像前者一样对每个属性进行处理。这使得 Vue 3.x 的响应式系统更加高效、灵活
javascript
// 创建一个响应式对象
function reactive(obj) {
return new Proxy(obj, {
get(target, key, receiver) {
console.log(`Getter: ${key}`);
const value = Reflect.get(target, key, receiver);
// 如果属性值是对象,递归地返回代理对象
return typeof value === 'object' ? reactive(value) : value;
},
set(target, key, value, receiver) {
console.log(`Setter: ${key}`);
// 使用 Reflect.set 设置属性值
const result = Reflect.set(target, key, value, receiver);
// 触发更新
// 这里可以加上通知更新的逻辑,例如触发重新渲染
return result;
}
});
}
2、双向绑定
Vue的双向绑定是指数据模型Model
和视图View
之间的同步关系是双向的,当一个改变时,另一个也会相应地发生变化。在Vue中,最常见的双向绑定是通过v-model
指令实现的,通常用于表单元素(如<input>
、<textarea>
、<select>
)。
javascript
<template>
<input v-model='myValue'/>
</template>
相当于
javascript
<template>
<input @input='onInput' :value='myValue' />
<span>{{myValue}}</span>
</template>
<script>
export default{
data(){
return {
myValue:'',
}
},
methods:{
onInput(e){
this.myValue=e.target.value;
console.log(this.myValue)
}
}
}
</script>
当用户在表单元素中输入内容时,input
事件触发,将输入的新值反映到数据模型;反之,当数据模型的值改变时,相应的value
属性的变化会导致视图的更新(数据驱动视图)。
这就实现了双向绑定
3、虚拟dom
Vue使用虚拟DOM(Virtual DOM)作为一种性能优化手段,以提高页面渲染的效率。虚拟DOM是一个内存中的表示真实DOM结构的JavaScript对象树,通过对比新旧虚拟DOM的差异,最终只对发生变化的部分进行实际的DOM操作,从而减少了对真实DOM的直接操作,提高了性能。
以下是Vue虚拟DOM的基本工作原理:
-
初始渲染: 当页面首次加载或数据发生变化时,Vue会创建一个虚拟DOM,该虚拟DOM对应着整个组件的DOM结构。
-
更新触发: 当数据发生变化时,Vue会生成一个新的虚拟DOM树。
-
虚拟DOM Diff(差异)算法: Vue会将新旧虚拟DOM进行比较,找到两者之间的差异。这个比较过程被称为虚拟DOM Diff算法。
- 快速比较: 通过对比两个虚拟DOM树的差异,Vue能够快速定位到发生变化的节点,而无需对整个DOM树进行比较。
-
差异更新: Vue会根据差异,只更新发生变化的部分到真实DOM中,而不是重新渲染整个DOM树。
- 最小化DOM操作: 这个过程可以大大减少实际的DOM操作次数,从而提高性能。因为对真实DOM的操作是相对昂贵的,通过最小化这些操作,可以更有效地更新用户界面。
-
渲染到真实DOM: 最后,将更新后的虚拟DOM渲染到真实DOM中,使视图与数据保持同步。