38

I don't understand the difference between v-model and .sync used on a component.

<my-component v-model="myVar">

V-model is a shorthand for binding a variable (myVar) to the component property 'value' and listening to the 'input' event emitted from the component to update the variable 'myVar'.

<my-component v-bind:prop1.sync="myVar">

.sync is a shorthand for binding a variable (myVar) to a component property ('prop1' in this case) and listening to the 'update:prop1' event emitted from the component to update the variable 'myVar'.

I know that by default v-model only works with the 'value' property and the 'input' event but even that can be customized using the 'model' option in the component.

Would be nice if anybody could explain the difference to me or when to use what.

Here is an example where I used the same component in three different ways: 1) manual binding + event listening 2) .sync 3) v-model

Peter Petrus
  • 699
  • 3
  • 8
  • 15

2 Answers2

41

For Vue.js 2 both pretty much do the same thing - enable two-way binding, although .sync is more versatile. It was added after v-model was added for components. .sync allows to use v-model logic for more than one prop. Let's compare:

<comp :value.sync="username" :age.sync="userAge" />

expands to:

<comp :value="username" :age="userAge" @update:name="val => userName = val" @update:age="val => userAge = val" />
<comp v-model="userName" />

expands to:

<comp :value="username" @input="val => username = val" />

The differences as we can see are:

  • the default prop name v-model always binds to property called value

  • .sync allows you to use multiple props

  • the event name emitted from component (@update for .sync and @input for v-model)

One very interesting feature of .sync is its special handling of objects. The .sync modifier when used on an object will set multiple props at once (more here)

Which one to use? It is a standard pattern to use property value as the key value carrier for a component. In this situation if you have value property and want to enable 2-way binding for it then use v-model. In all other cases use .sync

tony19
  • 125,647
  • 18
  • 229
  • 307
husayt
  • 14,553
  • 8
  • 53
  • 81
  • 1
    Wanted to add a point that you missed. We don't necessarily need to use the 'value' prop and the 'input' event. We can modify it - https://www.digitalocean.com/community/tutorials/how-to-add-v-model-support-to-custom-vue-js-components – Sanil Khurana Jun 24 '20 at 03:07
  • Do you think it makes sense for someone developing components for other develops to support both the `v-model` and `.sync` apis for their 'single editable prop' components? i.e. emit both `input` and `update:value`? I worry about emitting too many events, but also figure that won't be an issue – Max Coplan Oct 02 '20 at 20:04
  • It says deprecated for me, see also: https://eslint.vuejs.org/rules/no-deprecated-v-bind-sync.html – Melroy van den Berg Nov 29 '21 at 20:50
  • 1
    @husayt, I think there´s a typo in the 2nd line of code: `@update:value="val => userName = val"`. In other words, the property that, when changed, triggers the update is `value` and not `name`. – rubebop Mar 21 '22 at 17:28
8

There isn't much difference, so much so that there is a plan to potentially merge them in Vue 3:

https://github.com/vuejs/rfcs/pull/8

In cases where a component has a natural candidate for two-way binding you'd use v-model. So text inputs, checkboxes, etc. would all use v-model. Similarly it might make sense in the context of a component with a concept of selection. You could use sync instead but it isn't typically what other developers would be expecting.

In Vue 2 you can only have a single prop/event wired up to v-model. If you want two-way binding for multiple props/events then you'd have to use sync.

Vuetify contains several examples of components that use both v-model and sync. For example, v-autocomplete:

https://vuetifyjs.com/en/components/autocompletes

This uses v-model for the selected value but it also uses sync for error and search-input.

skirtle
  • 27,868
  • 4
  • 42
  • 57