Vue’s new and improved prop.sync
In Vue 2.3, the .sync
modifier, which was removed in the past, has been reintroduced in a new way.
This post is going to explore two approaches to passing props down to child components and passing up the updates. The first is the familiar v-model
and it’s Vue 2.2 update, and the second will be with .sync
.
v-model
The parent component binds speaks
to the child with the v-model
directive.
<template>
<doggie v-model="speaks" />
</template><script>
export default {
data: {
speaks: 'bark!'
}
}
</script>
Meanwhile the child declares a value
prop which has the value of speaks
.
It also emits an input
event when the actual <input />
fires its own input
event. The value passed to that event will update the parent’s speaks
.
<template>
<input :value="value" @input="$emit('input', $event.target.value)" />
</template>export default {
props: ['value'],
}
The child component using the prop value
is just a default behavior, just like the name of the emit being input
. Both can be overridden (if you’re using Vue 2.2+) by adding model
to the child like this:
export default {
props: ['sound'],
model: {
prop: 'sound',
event: 'updateSound'
},
}
Furthermore, now you can still declare thevalue
prop for the child, except it won’t be tied to v-model
anymore. Here’s the final working example.
.sync
Disclaimer: This works in Vue 2.3+
On obvious difference between v-model
and .sync
is the syntax. Here’s how the parent component could look.
<template>
<doggie :size.sync="size" />
</template><script>
export default {
data: {
size: 'little'
}
}
</script>
With .sync
, the child doesn’t need a value
prop. Instead it uses the same prop name you synced in the parent.
It also instead of emitting an input
event to update the prop, you emit the conveniently named event update:prop-name
. This is the main difference between the old .sync
and the new one. Now we need to emit this update event to stay consistent with how we update parent component data like how we do with v-model
.
This is how the child could look.
<template>
<input :value="size" @input="$emit('update:size', $event.target.value)" />
</template>export default {
props: ['size'],
}
Another difference is that you can sync more than one prop to a component. Here’s the final working code.
Thank you for checking this post out. If there’s something you feel I’ve left out, feel free to share in the comments below.