2
votes

I am trying to implement two-way data binding (v-model) on a custom component.
I read the docs and found this:

the value of lovingVue will be passed to the checked prop. The lovingVue property will then be updated when <base-checkbox> emits a change event with a new value.

Notice the part where it says: property will then be updated when <base-checkbox> emits a change event with a new value

I have a parent component (HelloWorld.vue), which has a list of child components (Note.vue). Each of this note is draggable. The parent component has a list of child components represented as array of objects, for each element of this array, one instance of note.vue is created using v-for and bound to the array element using v-model like this:

 <template v-for="(note, index) in notes">
    <note v-model="note.value" :key="note.id" :ref="note.id"></note>
  </template>

and note.vue accepts the v-model like this:

export default {
  name: "Note",
  model: {
    prop: "note",
    event: "even-this-is-not-working"
  },
  props: {
    note: {
      type: Object,
      default: () => null
    }
  },

Whenever a note is dragged around the updates properties of note prop internally (but does not emit the updated note), but still the bound note in the parent component gets updated. (I have verified this with vue dev tools as well as by adding a watcher on the note in parent component).

Code Sandbox: https://codesandbox.io/s/custom-v-model-binding-bz61o?file=/src/components/HelloWorld.vue
Try to add a note by clicking Add Note and drag it around, you will see that the watcher in parent is fired even when there is no event being emitted from Note.vue.

Am I understanding the concept wrong? or is there any problem with the code?

1

1 Answers

1
votes

That's because you pass around objects and in JS, objects are passed by reference. Content of prop note inside your Note component is the same object as notes[x].value by identity (same place in the memory) so updates to its properties in Note component must be observable in your HelloWorld parent component

v-model would be needed only if you would like to replace the object in notes[x].value by different object created inside the Note component...

let user = { name: 'John' };

console.log(user.name);

let admin = user; // admin is just reference to existing object

admin.name = 'Pete';

console.log(user.name); // 'Pete', changes are seen from the "user" reference