Skip to content

Vue's Data Binding

Although a basic understanding of Vue's syntax and concepts is assumed, this section will explain data binding especially in the context of components.

To pass data from a parent to child component we use properties that we pass to the child component (via v-bind:propName or its shorthand :propName). Since altering property values within a receiving child component is considered bad practice and should be avoided at all costs, passing props to child components is a one-way data binding in the direction to the child component (down the component tree) only.

We can also pass data from the child to its parent component via emitting events (optionally with payloads) from the child component and receiving those in the parent component (v-on:emitName or its shorthand @emitName). This again is a one-way binding now up the component tree. This technique is (among other use cases) used when a child component needs to change the value of one (or more) of its properties. Since we already mentioned that altering props directly within the child component must be avoided since the one-way data binding would cause inconsistencies between the values of the parent and child component values, we need to emit the new value from the child component to its parent that then handles the actual update of the variables value which then again, will be passed back to the child component via the persistent property binding.

To simplify this use case, vue provides the concept of modelValues which create a two-way binding of a variable between parent and child component. They are created using the v-model:modelName syntax. In the end v-model is just a shorthand for the prop declaration on the one hand :modelName="initialValue" and its update event handling @update:modelName="(newValue) => modelName = newValue".

Now components can define additional modelValues via the built-in defineModel() macro. If no string (name) is passed to it the default name will be modelValue and hence can be shortly bound from the parent component by just declaring v-model="parentVariableName".

But v-model can also accept an argument

vue
<MyComponent v-model:title="bookTitle" />

In the child component we can support the corresponding argument by passing a string to defineModel() as its first argument:

vue
<script setup>
const localTitle = defineModel('title')
</script>

<template>
  <input type="text" v-model="localTitle" />
</template>

The different naming here is just for demonstration purposes to point out exactly how the name mapping works.

For further reference and a deep dive into this topic please have a look to Vue's official docs on this topic.