2 way binding - sikaeducation/vue-curriculum GitHub Wiki
Official Vue docs on 2-way binding
Most props in Vue are bound in one direction only- a change in the source is reflected in the destination:
<template>
<p>{{ counter }}</p>
<button @click="() => data += 1">Increment</button>
</template>
<script>
export default {
data() {
return {
counter: 1
}
}
}
</script>
Any time counter
is changed, the value in the <p>
tag updates and that's the single source of truth for what the counter currently is.
With form inputs however, we usually want the binding to go both ways: A change in the state is reflected in the input, and a change in the input is reflected in state. In Vue, we do this with the v-model
property:
<template>
<form>
<input v-model="searchTerm" />
</form>
</template>
<script>
export default {
data() {
return {
searchTerm: ""
}
}
}
</script>
Now, the state can be changed from either direction. This is a shorthand for binding the value of the input to state and updating the state on the change
event.
You can use v-model
on components (not just HTML elements), but it's a little trickier:
// SomeComponent.vue
<template>
<form>
<MyCoolCustomInput v-model:searchTerm="searchTerm" />
</form>
</template>
<script>
import MyCoolCustomInput from '@/components/MyCoolCustomInput';
export default {
components: {
MyCoolCustomInput,
},
data() {
return {
searchTerm: ""
}
}
}
</script>
// MyCoolCustomInput.vue
<template>
<form>
<input :value="searchTerm" @input="$emit('update:searchTerm', $event.target.value)" />
</form>
</template>
<script>
export default {
props: {
searchTerm: ""
}
}
</script>
Watch the syntax on that very carefully. Some notes:
-
v-model:searchTerm="searchTerm"
- The firstsearchTerm
is what the prop will be called in the child component, the second is what it's called in the parent - The binding on the child component is 1-way. Bind the value of the HTML element on the child component to whatever you named the prop.
- Fire an event when the child component changes in the format
update:propName
.v-model
will listen for this change automatically. - Pass the updated value into the event. You can access this on
<input />
elements with$event.target.value
.