--- title: defineModel Object Properties Must Be Replaced, Not Mutated impact: HIGH impactDescription: Mutating object properties via defineModel doesn't emit update events, breaking parent sync type: gotcha tags: [vue3, v-model, defineModel, objects, reactivity, two-way-binding] --- # defineModel Object Properties Must Be Replaced, Not Mutated **Impact: HIGH** - When using `defineModel()` with objects or arrays, directly mutating nested properties like `model.value.prop = x` does NOT emit the `update:modelValue` event. The parent component never receives the change notification, causing silent sync failures. This happens because Vue only detects when the `model.value` reference itself changes, not when properties of the object are mutated in place. ## Task Checklist - [ ] Never mutate object properties directly: `model.value.prop = x` - [ ] Always create a new object reference when updating: `model.value = {...model.value, prop: x}` - [ ] For arrays, use spread or slice: `model.value = [...model.value, newItem]` - [ ] Consider using structuredClone for deeply nested objects **Incorrect - Mutation without event emission:** ```vue ``` **Correct - Replace object reference to trigger event:** ```vue ``` ## Deep Nesting Requires Full Path Replacement ```vue ``` ## Race Condition Warning with Spread Operator When multiple updates occur rapidly, earlier changes can be lost: ```vue ``` ## Alternative: VueUse's useVModel with Deep Option For complex objects, consider VueUse: ```vue ``` ## Reference - [Vue.js Component v-model](https://vuejs.org/guide/components/v-model.html) - [GitHub Discussion: defineModel with objects](https://github.com/orgs/vuejs/discussions/10538) - [SIMPL Engineering: Vue defineModel Pitfalls](https://engineering.simpl.de/post/vue_definemodel/)