当前位置: 首页 > 知识库问答 >
问题:

前端 - Vue 3中Object.assign与响应式数据?

林国安
2024-01-02

前端小白,在学习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官方文档中有如下说明
image.png

对于上面的代码和文档描述,按理说结果是姓名:121231,但是实际运行结果是姓名:hh

如果Object.assign(person,{aa:"121231",bb:12131})不存在,或者说不是先执行,确实是无法在页面上修改数据为hh,但是只要这一行代码存在并且先执行,就会修改为hh

根据上述现象,初步判断可能是Object.assign(person,{aa:"121231",bb:12131})代码副作用,查了MDN,说该API会调用get/set方法。

image.png

虽然vue是通过监听set/get方法实现的响应式渲染,上述mdn内容只是说明了Object.assign(person,{aa:"121231",bb:12131})为什么有效,但是还是不能解决我的疑惑

希望大佬说一下原因

共有1个答案

臧威
2024-01-02

你的问题主要在于理解Vue 3的响应式系统和Object.assign如何交互。

Vue 3使用了一个新的响应式系统,该系统基于Proxy对象,而不是之前版本中的Object.defineProperty。当你在Vue组件中创建一个响应式对象时,Vue实际上会返回一个特殊的Proxy对象,该对象拦截了读取和设置属性的操作。当属性被设置时,Vue会知道该属性已经被修改,并重新渲染依赖于该属性的部分。

现在,让我们看看Object.assign是如何工作的。这个函数会遍历源对象的所有可枚举属性,并将它们复制到目标对象中。如果目标对象已经有了同名属性,那么这些属性将被源属性覆盖。

在你的代码中,Object.assign(person,{aa:"121231",bb:12131})会将{aa:"121231",bb:12131}这个对象的所有属性复制到person对象中。由于person是一个Vue响应式对象,当它的属性被设置时,Vue会知道这些属性已经被修改,并重新渲染依赖于这些属性的部分。

然而,你需要注意的是,Object.assign并不会返回一个新的对象,而是返回目标对象。在你的代码中,person就是目标对象。因此,当你执行person = {aa:"hhh",bb:13}person = {aa:"hh",bb:132}时,你实际上是在改变person的引用,而不是它的属性。由于Vue不会检测到对象引用的改变(只有当一个响应式对象的引用被改变时,Vue才会标记它为“dirty”),因此Vue不会重新渲染依赖于person的任何部分。

这就是为什么你看到的结果是“姓名:hh”,而不是“姓名:121231”。如果你希望在改变对象属性时能够触发Vue的重新渲染,你应该直接设置对象的属性,而不是改变对象的引用。例如,你可以使用解构赋值来更改对象的属性:

person = { ...person, aa: "hh", bb: 132 };

在这个例子中,由于我们没有改变person的引用,只有它的属性被改变,因此Vue会检测到这个变化并重新渲染依赖于person的任何部分。

 类似资料:
  • 例如我创建了一个dataHook main.ts中 页面有个按钮就执行v.value += 1,为什么console.log还是原值1呢?

  • 本文向大家介绍Vue3 响应式侦听与计算的实现,包括了Vue3 响应式侦听与计算的实现的使用技巧和注意事项,需要的朋友参考一下 响应式侦听和计算 有时我们需要依赖于其他状态的状态——在 Vue 中,这是用组件 计算属性 处理的,以直接创建计算值,我们可以使用 computed 方法:它接受 getter 函数并为 getter 返回的值返回一个不可变的响应式 ref 对象。 我们先来看看一个简单的

  • 如题,定义一个组件,设置 props 如下: 当我直接定义 的时候,会提示这样会失去响应性 所以想问下,如何可以将这样的定义,转为响应性

  • 在vue3框架中,我使用ref定义了一个变量,但是发现在更新其数据之后,页面上并不会有响应式变化,具体表现是在更新数据之后不会出现表格最前面的选择框 数据定义 数据初始化,其中list是一个数组,具有唯一的id属性 组件A中定义了计算属性rowSelection 当点击一个按钮之后,触发BatchEdit函数,通过emit抛出新的rowSelection 在父组件中进行事件定义并更新内容 rowS

  • vue3怎么深拷贝ref和reactive对象让其保持 响应式属性? 因为用json.parse(json.stringify())的话会使其失去响应式

  • 问题内容: 假设我有一个变量,并且想要设置一些默认值。 这两种选择的优点/缺点是什么? 使用对象传播 或使用Object.assign 这就是让我感到奇怪的承诺。 问题答案: 这并不一定是详尽无遗的。 传播语法 优点: 如果编写代码以在没有本机支持的环境中执行,则可以只编译此语法(与使用polyfill相对)。(例如,使用Babel。) 不太冗长。 缺点: 最初编写此答案时,这只是一个建议,而不是