文章目录
- vue3 ref reactive响应式数据 赋值的问题
- 场景1:将响应式数据赋值请求后的数据
- 错误示范:直接赋值
- 正确写法
- 场景2:响应式数据解构之后失去响应式
- 原因分析
- 解决办法 toRefs/toRef方法创建ref引用对象
vue3 ref reactive响应式数据 赋值的问题
doing 遇见就记录,最后更新时间23.8.30
场景1:将响应式数据赋值请求后的数据
错误示范:直接赋值
以数组为例,对象也是一样的操作。
let list = ref([])
//let list = reactive([])
async function getList() {
list = await httpGetList(); // 直接赋值错误
}
// 请求
function httpGetList() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1, 2, 3, 4, 5])
}, 500)
})
}
ref
定义的属性等价于reactive({value:xxx})
,所以reactive、ref
直接重新赋值丢失响应是因为引用地址变了
正确写法
- 方法1:
ref.value
,代码中更为清晰地表明响应式数据
list.value = await httpGetList();
- 方法2:包一层
reactive
,可以将一个模块的变量包在一个reactive
里面,当作vue2的data
let data = reactive({
list:[]
})
async function getList() {
data.list = await httpGetList();
}
ref
定义的属性等价于reactive({value:xxx})
,方法2其实就是参考了该方式。
- 方法3:更推荐方法1和方法2
let list = reactive([])
async function getList2() {
let resp = await httpGetList()
list.push(...resp)
}
场景2:响应式数据解构之后失去响应式
原因分析
reactive内部的实现是创建一个代理对象Proxy,以及进行了一系列处理。reactive失去效应是不在于Vue而在于Proxy对象本身。
解构相当于将该变量重新赋给(基础数据传值,引用类型传地址)了一个新变量,所以解构之后是一个基础数据则会响应式丢失。如果解构之后是一个引用类型,相当于操作的地址还是被Proxy监管,所以响应式不会丢失。
案例
比如解构之后是基础类型的数据,那么解构相当于copy了一个值。访问时直接访问的这个copy值,跳过了代理,所以不会触发get
和set
。
解决办法 toRefs/toRef方法创建ref引用对象
解构赋值主要还是赋值!对于基本数据类型,函数传递或者对象解构时,会丢失原始数据的引用。,
toRef(响应式对象,该对象的属性)
创建一个ref对象
,该ref对象
的value
值指向参数对象中的某个属性
ref对象的value值改变,参数对象中的该属性也会改变,反之也会改变,因为指向同一个地址!本质是引用,与原始数据有关联
toRefs(obj)
:返回一个和参数一致的普通对象,只不过属性的值都变成了ref对象,相当于每个属性都执行了一次toRef
。