Vue 3中Object.assign与响应式数据?
前端小白,在学习Vue 3 响应式数据的时候,遇到了一个问题
<script lang="ts"> export default{
name:"test",
}
</script>
<script lang="ts" setup>
import {toRefs,ref,reactive} from "vue";
let person = reactive({aa:"abc",bb:123})
function c(){
console.log(1)
console.log(person)
Object.assign(person,{aa:"121231",bb:12131})
person = {aa:"hhh",bb:13}
person = {aa:"hh",bb:132}
console.log(person)
}
</script>
<template>
<span>姓名:{{person.aa}} </span> <br>
<button @click="c">点击修改数据</button>
</template>
vue3官方文档中有如下说明
对于上面的代码和文档描述,按理说结果是姓名:121231
,但是实际运行结果是姓名:hh
如果Object.assign(person,{aa:"121231",bb:12131})
不存在,或者说不是先执行,确实是无法在页面上修改数据为hh,但是只要这一行代码存在并且先执行,就会修改为hh
根据上述现象,初步判断可能是Object.assign(person,{aa:"121231",bb:12131})
代码副作用,查了MDN,说该API会调用get/set方法。
虽然vue是通过监听set/get方法实现的响应式渲染,上述mdn内容只是说明了Object.assign(person,{aa:"121231",bb:12131})
为什么有效,但是还是不能解决我的疑惑
希望大佬说一下原因
回答:
造成这个现象的原因是 Object.assign
修改了 person
的属性,触发了组件更新,从编译完成后的代码我们可以看出,template 最终被编译成了 render function
,其中引用了 person.aa
,也就是说 render function
会被收集为 person.aa
的依赖
当 Object.assign(person,{aa:"121231",bb:12131})
被执行,也就意味着 render function
会被重新执行,但这里很重要的一点是,vue的更新是异步的,状态变化驱动的更新会被合并到下一个 nextTick
执行
综上,这里的执行顺序其实是
Object.assign(person,{aa:"121231",bb:12131})
- person = {aa:"hhh",bb:13}
person = {aa:"hh",bb:132}
- ...
render function
这就是为什么步骤3中 person = {aa:"hh",bb:132}
能影响渲染结果,但重新赋值也导致其丢掉了响应性
回答:
这跟 Vue 无关,这是语法问题。
const a = ref(0); // <-- 创建一个 Ref 对象,value 是 0,然后用 a 指向这个变量a.value = 1; // 将 a 的 value 修改为 1,a 仍然有响应式
a = 2; // <-- 创建一个常量,值为 2,然后把 a 指向这个常量。a 不在有响应式,因为常量 2 没有响应式
所以,因为 Object.assign
修改的是目标对象的某个键上的值,所以不影响响应式。而赋值直接就把变量指向的目标改变了,所以就没有响应式了。
以上是 Vue 3中Object.assign与响应式数据? 的全部内容, 来源链接: utcz.com/p/935286.html