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:
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:
How do I listen (from the parent) for the changes that the child component did via v-model
?
The ref
means it's a reference and to track/watch it, it should be changed, not the object it reference to:
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