Search code examples
vue.jsvuejs3vue-composition-api

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


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)


Solution

  • 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