Vue 3与 Vue 2响应式的区别
1. Vue 3响应式原理
Vue3 使用 Proxy 对象来实现响应式系统,主要依赖 reactive 和 ref 函数。
1.1. 核心概念
1. reactive 函数
- reactive 函数接收一个对象并返回一个代理对象(Proxy),这个代理对象能够在属性被读取和修改时进行依赖收集和触发更新。
import { reactive } from 'vue';
const state = reactive({ count: 0 });2. ref 函数
- ref 函数用于创建一个包含单一值的响应式对象,适用于基本类型(如字符串、数字)以及引用类型。
import { ref } from 'vue';
const count = ref(0);3. 依赖收集和追踪
- 当响应式对象的属性被读取时,当前的副作用(effect)会被记录为该属性的依赖。当该属性变化时,所有依赖于该属性的副作用都会被重新执行。
1.2. Proxy 对象的优势
动态属性检测: Proxy 可以动态地拦截对属性的读取和写入操作,支持新增或删除属性时的响应式更新。
性能优化: 相比于 Vue2 中的 Object.defineProperty,Proxy 的性能和灵活性更高。
2. Vue 2 响应式原理
Vue 2 使用 Object.defineProperty 来实现响应式系统,主要依赖 data 和 computed。
2.1. 核心概念
1. data 选项
- Vue 2 通过 data 选项定义响应式数据,Vue 会递归遍历 data 对象的属性,并使用 Object.defineProperty 将每个属性转换为 getter 和 setter,从而实现响应式。
new Vue({data: {count: 0}
});2. computed 选项
- computed 属性用于定义计算属性,这些属性依赖于其它响应式属性,并且会在依赖发生变化时自动重新计算。
new Vue({data: {a: 1,b: 2},computed: {sum() {return this.a + this.b;}}
});3. 依赖收集和追踪
- Vue 2 的依赖收集是在属性的 getter 中进行的,当响应式属性被读取时,当前的渲染函数会被记录为该属性的依赖。当属性变化时,通过 setter 触发依赖更新。
2.2. Object.defineProperty 的局限性
新增/删除属性的限制: 无法动态检测对象属性的新增或删除,必须使用 Vue.set 或 Vue.delete 来确保响应式。
数组的局限性: 数组的某些变动(如索引赋值)无法被侦测,需要特殊处理。
3. 对比总结
1. 实现方式
Vue3: 使用 Proxy 实现响应式。
Vue2: 使用 Object.defineProperty 实现响应式。
2. 动态属性支持
Vue3: 可以动态地响应新增和删除属性。
Vue2: 无法动态地响应新增和删除属性,需要使用 Vue.set 和 Vue.delete。
3. 性能和灵活性
Vue3: Proxy 提供了更高的性能和灵活性,能够更高效地处理响应式更新。
Vue2: Object.defineProperty 在处理深层嵌套对象和数组时性能较差,并且有一定的局限性。
