Search code examples
vuejs3

Vue3 @update:modelValue NOT working on objects?


This is basic stuff, I'm missing something obvious. I have reproduced the basic v-model example from the docs: https://vuejs.org/guide/components/v-model.html#basic-usage and it is working fine. I have added the: @update:modelValue="modelUpdated" handler and it works: the child component detects a change and emits the update event and everything is fine:

Vue.js Playground

BUT, when I change the example from the primitive value (number) to object the event is no longer emitted! So, instead of:

const countModel = ref(0)

now I'm using:

const countModel = ref({
  name: "Joe",
  age: 30
})

The object IS changed, but I'm not being notified. Tried watching that object too, did not work:

Vue.js Playground

How do I listen (from the parent) for the changes that the child component did via v-model?


Solution

  • The ref means it's a reference and to track/watch it, it should be changed, not the object it reference to:

    Playground

    function update() {
      model.value = {...model.value, age: model.value.age + 1};
    }
    

    I actually consider this as a weak part of Vue, since creating a big object each time its property changes could be slow, non meaning that any references to nested object are destroyed.

    On the other hand you can just watch the object:

    watch(countModel.value, modelUpdated);
    

    But that doesn't imply the modelUpdate event so v-model is useless and you'd better use an usual prop but Vue considers props readonly but doesn't protect object props from mutating since "it's expensive".

    So I would say the whole 2-way binding of objects looks not well designed and consistent in Vue.

    But in general I'd say v-model is used for promitive types and simple objects without nesting, if I want to pass a complex object I'd rather use provide/inject or an import that exported into child components