vue3 reactive unexpected behaviour

cla*_*.io 1 vue.js vuejs3 vue-composition-api

i've a reactive object, on the save function i call toRaw in order to remove de object reactivity, but, when i change the reactive object props, also the group object is changing.... How???


const newGroup = reactive<Group>({ id: undefined, name: '', enabled: false })

const handleSave = () => {
      const group = toRaw(newGroup)
      persist(group).then(() => {
        newGroup.id = undefined
        newGroup.name = 'demo'
        console.log(isReactive(group)) //say false but the group.name value is demo
      })
     
    }
Run Code Online (Sandbox Code Playgroud)

destructuring the reactive obj as const group = { ...newGroup } looks like it works, still no understand why toRaw is not working.

编辑:

整个问题来自于处理反应性对象时缺乏控制感,例如:

下面的计算对象从存储中检索一个列表,然后将其绘制在模板中作为表的行,单击所选元素的状态就会发生变化。在函数中,我被迫解构记录,以避免修改在持久化之前触发启用的更改是否有更好的方法?我应该创建只读组吗?


//in setup()
const groups = computed <Group []> (() => getters ['registry / groups'])

const toggle = (record: Group) => {
    const group = { ...record } 
    group.enabled = !group.enabled
    persist(group)
}

//in template
  <a-menu-item @ click = "toggle (record)">
Run Code Online (Sandbox Code Playgroud)

Dan*_*iel 7

预期的行为,但描述可能不够详细并导致一些混乱。

根据原始文档

返回反应式或只读代理的原始对象。这是一个逃生舱口,可用于临时读取而不产生代理访问/跟踪开销或写入而不触发更改。不建议保留对原始对象的持久引用。谨慎使用。

当您使用 时发生的情况是,您将返回在没有toRaw代理的情况下传递给reactive函数的原始对象。这意味着该对象是同一个对象(在示例中)。如果您使用而不是代理本身,则仅允许您“转义”绑定到对象的反应性/侦听器。即使对象更新,反应性(滴注到 DOM)也不会应用。ogtoRawtoRaw

这是一个例子:

let o = {name:"Ja Ja"};
let m = Vue.reactive(o);
let g = Vue.toRaw(m);

console.log(o.name, m.name, g.name);

g.name = g.name + " Ding Dong";

console.log(o.name, m.name, g.name);

console.log("Is 'm' same as 'o'? ", m == g);
console.log("Is 'g' really just 'o'? ", o == g);
Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue@next/dist/vue.global.prod.js"></script>
Run Code Online (Sandbox Code Playgroud)

如果要创建一个不会更新原始对象的对象,最简单的方法就是克隆它。

大多数时候你可以使用JSON.parse(JSON.stringify(o)). 需要注意的是,如果您有循环引用(即{a:b, b:a}),您就会遇到问题。

另一种选择是使用解构const copy = {...o}。这里需要注意的是它是一个浅拷贝。示例o = {a:{b:"I will update"}, c:"I won't"},其中copy.a仍然是相同的对象o.a

那看起来就像

let o = {name:"Ja Ja"};
let m = Vue.reactive(o);
let g0 = {...Vue.toRaw(m)}; // destructure
let g1 = JSON.parse(JSON.stringify(Vue.toRaw(m))); // clone with json
Run Code Online (Sandbox Code Playgroud)

或者,您也可以使用一些为您处理克隆对象的库。