Vue.js comes with 2 built-in directives that are used often.
They’re the v-model
and v-bind
directives.
They serve different purposes.
In this article, we’ll look at the differences between the v-model
and v-bind
directives in Vue.js
v-bind
The v-bind
lets us do one-way binding between the parent and child components.
We can pass data from the parent to the child component.
The child component will receive the data as props.
For instance, we can write:
App.vue
<template>
<div id="app">
<HelloWorld :name="name" />
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
export default {
name: "App",
components: {
HelloWorld,
},
data() {
return {
name: "jane",
};
},
};
</script>
components/HelloWorld.vue
<template>
<div class="hello">hello {{ name }}</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
name: String,
},
};
</script>
In the App.vue
component, we have the HelloWorld
component in the template with the :name
directive.
:name
is short for v-bind:name
.
So we can also write:
<template>
<div id="app">
<HelloWorld v-bind:name="name" />
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
export default {
name: "App",
components: {
HelloWorld,
},
data() {
return {
name: "jane",
};
},
};
</script>
name
is the prop name.
And we set the name
reactive property as the value of the name
prop.
In HelloWorld.vue
, we register the name
prop in the props
property.
We set the data type of the prop to String
.
This is the data type that’s expected to be passed in.
And the value of the name
prop isn’t a string, then an error will be logged in the console.
Then we can reference the prop’s value in the template or reference it in the component with this.name
.
Therefore, we should see ‘hello jane’ displayed.
v-bind
lets us pass data from parent component to the child.
v-model
The v-model
directive provides us with 2 way binding between parent and child components.
It’s the equivalent of adding the value
prop and emitting the input
event.
For instance, we can write:
App.vue
<template>
<div id="app">
<CustomInput v-model="name" />
<p>{{ name }}</p>
</div>
</template>
<script>
import CustomInput from "./components/CustomInput";
export default {
name: "App",
components: {
CustomInput,
},
data() {
return {
name: "jane",
};
},
};
</script>
components/CustomInput.vue
<template>
<div>
<input :value="value" @input="$emit('input', $event.target.value)" />
</div>
</template>
<script>
export default {
name: "CustomInput",
props: {
value: String,
},
};
</script>
In App.vue
, we have the CustomInput
component that’s bound to the name
reactive property with v-model
.
We display the name
value below the CustomInput
.
The in the CustomInnput
component, we register the value
prop.
And we pass the value
into value
prop of the input element.
Also, we listen for the input event.
And when it’s emitted, we call $emit
to emit the input
event as indicated in the first argument of emit.
$event.target.value
has the inputted value.
Since CustomInput
takes the value
prop and emits the input
event, we can use v-model
to add 2-way binding between the 2 components.
And when we type in the input, we see the name
value displayed below changes.
We can also write:
<template>
<div>
<input :value="value" @input="onInput" />
</div>
</template>
<script>
export default {
name: "CustomInput",
props: {
value: String,
},
methods: {
onInput(event) {
this.$emit("input", event.target.value);
},
},
};
</script>
in CustomInput.vue
.
$emit
is the template is the same as this.$emit
in the onInput
method.
$event.target.value
is replaced with event.target.value
.
Conclusion
v-bind
provides us with one way binding from the parent component to the child.
And v-model
provides us with 2-way binding between the parent and child.