Vue3 的响应式和以前有什么区别,的响应式和以前有什么区别,Proxy 无敌?无敌?
主要介绍了Vue3 的响应式和以前有什么区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一
定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
前言
大家都知道,Vue2 里的响应式其实有点像是一个半完全体,对于对象上新增的属性无能为力,对于数组则需要拦截它的原型
方法来实现响应式。
举个例子:
let vm = new Vue({
data() {
return {
a: 1
}
}
})
// oops,没反应!
vm.b = 2
let vm = new Vue({
data() {
return {
a: 1
}
},
watch: {
b() {
console.log('change !!')
}
}
})
// oops,没反应!
vm.b = 2
这种时候,Vue 提供了一个 api:this.$set,来使得新增的属性也拥有响应式的效果。
但是对于很多新手来说,很多时候需要小心翼翼的去判断到底什么情况下需要用 $set,什么时候可以直接触发响应式。
总之,在 Vue3 中,这些都将成为过去。本篇文章会带你仔细讲解,proxy 到底会给 Vue3 带来怎么样的便利。并且会从源码
级别,告诉你这些都是如何实现的。
响应式仓库
Vue3 不同于 Vue2 也体现在源码结构上,Vue3 把耦合性比较低的包分散在 packages 目录下单独发布成 npm 包。 这也是目
前很流行的一种大型项目管理方式 Monorepo。
其中负责响应式部分的仓库就是 @vue/rectivity,它不涉及 Vue 的其他的任何部分,是非常非常 「正交」 的一种实现方式。
甚至可以轻松的集成进 React。
这也使得本篇的分析可以更加聚焦的分析这一个仓库,排除其他无关部分。
区别
Proxy 和 Object.defineProperty 的使用方法看似很相似,其实 Proxy 是在 「更高维度」 上去拦截属性的修改的,怎么理解
呢?
Vue2 中,对于给定的 data,如 { count: 1 },是需要根据具体的 key 也就是 count,去对「修改 data.count 」 和 「读取
data.count」进行拦截,也就是
Object.defineProperty(data, 'count', {
get() {},
set() {},
})
必须预先知道要拦截的 key 是什么,这也就是为什么 Vue2 里对于对象上的新增属性无能为力。
而 Vue3 所使用的 Proxy,则是这样拦截的:
new Proxy(data, {
get(key) { },
set(key, value) { },
})
可以看到,根本不需要关心具体的 key,它去拦截的是 「修改 data 上的任意 key」 和 「读取 data 上的任意 key」。
所以,不管是已有的 key 还是新增的 key,都逃不过它的魔爪。
但是 Proxy 更加强大的地方还在于 Proxy 除了 get 和 set,还可以拦截更多的操作符。
简单的例子
先写一个 Vue3 响应式的最小案例,本文的相关案例都只会用 reactive 和 effect 这两个 api。如果你了解过 React 中的
useEffect,相信你会对这个概念秒懂,Vue3 的 effect 不过就是去掉了手动声明依赖的「进化版」的 useEffect。
React 中手动声明 [data.count] 这个依赖的步骤被 Vue3 内部直接做掉了,在 effect 函数内部读取到 data.count 的时候,它就
已经被收集作为依赖了。