vue3 响应式
1)失去响应式原因:
- Vue3中的响应性使用了Proxy对象来替代Vue2中的Object.defineProperty。
-
而Proxy对象只能对整个对象进行拦截,而无法对对象的属性进行拦截。
因此,在使用解构赋值时,解构的对象会被转化为普通的JavaScript对象,而丢失了Vue3的响应性。 -
解构赋值实际上是创建一个新的对象,这个对象与原始对象不再具有相同的引用且没有经过响应性劫持 ,不再与Vue3的响应式系统关联
原始类型的赋值相当于按值传递
,引用类型的值就相当于按引用传递
// const a={ b:1} 假设a是个响应式对象
// const c=a.b 此时就是一个值跟当前的a 已经不沾边了
// 你直接访问c就相当于直接访问这个值 也就绕过了 a 对象的get ,也就失去响应式
// const a={ b:{c:3}}假设a是个响应式对象
// const c=a.b 当你访问a.b的时候就已经重新初始化响应式了,此时的c就已经是个代理的对象
// 你直接访问c就相当于访问一个响应式对象,所以并不会失去响应式
因为a.b 是引用类型,源码中判断如果是个object
那么就重新包装为响应式 - 解决方案:
可以使用toRefs函数来将解构赋值的结果转换为响应式的。toRefs函数可以接收一个响应式对象,并将其转换为具有响应性的Ref对象。这样,解构赋值的结果对象就能够保持响应性。
reactive函数将解构赋值的结果对象转化为响应式对象。reactive函数可以接收一个普通的JavaScript对象并返回一个具有响应性的Proxy对象,从而保持对象的响应性。
总结起来,Vue3中的解构赋值会丢失响应性是因为解构赋值创建了一个新的对象,该对象不再具有Vue3的响应性
2)reactive丢失响应式的情况1(直接赋值)
场景:
1.你定义了一个数据:
let data=reactive({
name:
""
,
age:
""
})
2.然后你请求了接口,赋值给data
let res=await getUserApi();
//请求接口
data=res.data;
//将返回的结果赋值给data
大错特错!!!
reactive丢失响应式的情况2(解构赋值)
场景:
1.你定义了一个数据:
let data=reactive({
name:
""
,
age:
""
})
2.然后你解构了
let {name}=data;
//解构赋值
大错特错!!!
了解响应式
1.ref 定义数据(包括对象)时,都会变成 RefImpl(Ref 引用对象) 类的实例,无论是修改还是重新赋值都会调用 setter,都会经过 reactive 方法处理为响应式对象。
2.但是 reactive 定义数据(必须是对象),是直接调用 reactive 方法处理成响应式对象。如果重新赋值,就会丢失原来响应式对象的引用地址,变成一个新的引用地址,
这个新的引用地址指向的对象是没有经过 reactive 方法处理的,所以是一个普通对象,而不是响应式对象。解构同理。
避坑办法:
避开直接赋值和结构,reactive直接包裹一个对象。
let data=reactive({
userData:{}
//里面定义一个对象,这样赋值就不会丢失响应式了。
})
//获取接口数据
let res=await getUserApi();
//请求接口
data.userData=res.data;
//将返回的结果赋值给data
简单数据类型使用ref()来进行定义。
这个很牛
https://blog.csdn.net/song854601134/article/details/127284112