目录
- 简介
- Vue2 响应式
- Vue2 响应式的局限性
- Vue3 响应式
- Vue3 响应式的优点
- Vue2 和 Vue3 响应式对比
简介
在 Vue 框架中,数据的响应式是其核心特性之一。当页面数据发生变化时,我们希望界面能自动更新,而不是手动操作 DOM。这就需要对数据进行监听,并在数据变更时触发 UI 重新渲染。
Vue2 和 Vue3 在实现响应式的方式上有所不同,Vue2 主要依赖 Object.defineProperty
,而 Vue3 则引入了 Proxy
,大大优化了响应式系统的性能和灵活性。它们都是通过函数来封装响应式对象,方便读取或更新数据时能够进行其他的操作。
Vue2 响应式
Vue2 使用 Object.defineProperty
来拦截对象属性的访问和修改,从而实现响应式。
const obj = {
a: 1,
b: 2,
c: {
x: 66,
y: 2,
}
}
function isObject(v) {
return typeof v === 'object' && v !== null;
}
function observe(obj) {
for (const k in obj) {
let v = obj[k];
if (isObject(v)) observe(v); // 递归遍历
Object.defineProperty(obj, k, {
get() {
console.log(`读取${k}, 值${v}`);
return v;
},
set(newVal) {
v = newVal;
console.log(`更新${k}, 值${v}`);
}
});
}
}
observe(obj);
obj.a;
obj.a = 101;
obj.c.x;
obj.c.x = 166;
Vue2 响应式的局限性
- 需要遍历对象的每个属性,性能较低。
- 不能检测到新增或删除的属性。
- 需要手动调用
Vue.set()
以确保新属性的响应式。
Vue3 响应式
Vue3 使用 Proxy
实现响应式,可以直接监听整个对象,而不是逐个属性。
const obj = {
a: 1,
b: 2,
c: {
x: 1,
y: 2,
}
};
function isObject(v) {
return typeof v === 'object' && v !== null;
}
function reactive(target) {
return new Proxy(target, {
get(target, k) {
console.log(`读取: ${k}, 值: ${target[k]}`);
// 读取时才递归生成代理
if (isObject(target[k])) return reactive(target[k]);
return target[k];
},
set(target, k, newVal) {
if (newVal === target[k]) return;
console.log(`更新: ${k}, 值${newVal}`);
target[k] = newVal;
return true;
}
});
}
const proxy = reactive(obj);
proxy.a;
proxy.a = 100;
proxy.c.x;
Vue3 响应式的优点
- 直接监听整个对象,无需遍历所有属性。
- 可以检测到属性的新增和删除。
- 具有更好的性能和更简洁的代码结构。
Vue2 和 Vue3 响应式对比
对比项 | Vue2 (Object.defineProperty ) | Vue3 (Proxy ) |
---|---|---|
监听方式 | 逐个属性拦截 | 整个对象拦截 |
深度监听 | 需要递归处理 | 访问时自动代理 |
属性新增删除 | 需要 Vue.set() 处理 | 可直接监听 |
数组监听 | 需要重写数组方法 | 原生支持 |
性能 | 需要遍历所有属性,较低 | 直接代理整个对象,更高 |
兼容性 | 兼容性好,支持 ES5 及以上 | 需要 ES6 Proxy 支持 |
Vue3 通过 Proxy
解决了 Vue2 的许多缺陷,使得响应式系统更加高效、灵活和简洁。因此,Vue3 的响应式能力远超 Vue2。