Home > OS >  Vue 3: Why can I not set two ref's with the same object
Vue 3: Why can I not set two ref's with the same object

Time:09-22

The problem:

Whenever I try to set two ref variables with the same Object they will share the same reactivity inside of the component.

When I click the checkbox ref1.test and ref2.test will change both, while the v-model is only for ref1.test

App.vue

<template>
  ref1: {{ ref1 }} ref2: {{ ref2 }}

  <input type="checkbox" v-model="ref1.test" />
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";
import { TestModel } from "@/TestModel";

export default defineComponent({
  setup() {

    const testObj = { test: false } as TestModel;

    const ref1 = ref<TestModel>({});
    ref1.value = testObj;

    const ref2 = ref<TestModel>({});
    ref2.value = testObj;

    return {
      ref1,
      ref2,
    };
  },
});
</script>

TestModel.ts

export interface TestModel {
  test?: boolean;
}

Can someone explain this or tell me if this is normal? (I know how to solve this, but I just wanna know why this is happening)

CodePudding user response:

The two ref's properties (ref1,ref2) refers to the same object which testObj and any change in one of those properties affects the original one, this is a javascript behavior, to avoid it try to clone the object deeply using structuredClone :

    const testObj = { test: false } as TestModel;

    const ref1 = ref<TestModel>({});
    ref1.value = structuredClone(testObj);

    const ref2 = ref<TestModel>({});
    ref2.value = structuredClone(testObj);

CodePudding user response:

Because Vue's reactivity is just proxy. It uses proxy so it knows what to do when a value change.

Proxy A (ref1) -> read/write testObj

Proxy B (ref2) -> read/write testObj

Docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

According to the Vue's docs

ref does the following:

If an object is assigned as a ref's value, the object is made deeply reactive with reactive().

Docs: https://vuejs.org/api/reactivity-core.html#ref

reactive does the following:

Returns a reactive proxy of the object.

...

The returned object and its nested objects are wrapped with ES Proxy

Docs: https://vuejs.org/api/reactivity-core.html#reactive

  • Related