In Vue 3, the v-model
has been completely changed and is no longer compatible with the Vue 2 syntax. In this article, I will explain how to use the v-model
in Vue 3, and what new functionality it brings. Before I do that, let's quickly look at the old syntax.
Old v-model syntax in Vue 2
Let's say we have a Parent component that contains a custom TextField component:
// ParentComponent.vue
<template>
<TextField v-model="providedUsername" />
</template>
<script>
import TextField from "./TextField";
export default {
name: "ParentComponent",
components: {
TextField
},
data: function() {
return {
providedUsername: null,
};
},
};
</script>
The TextField component is compatible with v-model
because it uses the value
property and emits the input
event:
// TextField.vue
<template>
<input type="text" :value="value" @input="$emit('input', $event.target.value)" />
</template>
<script>
export default {
name: "TextField",
props: {
value: String
}
};
</script>
New v-model in Vue 3
Now, let's see how to use the v-model
in Vue 3. Let's start with the parent component. The main change in Vue 3 is that instead of the data
function, we use the setup()
to define a reference to the username
field:
// ParentComponent.vue
<template>
<TextField v-model="providedUsername" />
</template>
<script>
import { ref } from "vue";
import TextField from "./TextField";
export default {
name: "ParentComponent",
components: {
TextField
},
setup() {
const providedUsername = ref(null);
return { providedUsername };
}
};
</script>
Now, let's define the TextField component:
// TextField.vue
<template>
<input type="text" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
</template>
<script>
export default {
name: "TextField",
props: {
modelValue: {
type: String
}
}
};
</script>
The big change is that for the v-model
we no longer use the value
property. Instead, in Vue 3, we use the modelValue
. A similar situation is with the event. Instead of the input
event, we emit the update:modelValue
.
In summary, to migrate v-model
from Vue 2 to Vue 3 rename :
- prop:
value
->modelValue
- event:
input
->update:modelValue
Custom v-model argument
Vue 3 allows to easily use a custom property name with v-model
. Let's say we want to use a username
property. In that case, the parent component will look like this:
// ParentComponent.vue
<template>
<TextField v-model:username="providedUsername" />
</template>
<script>
import { ref } from "vue";
import TextField from "./TextField";
export default {
name: "ParentComponent",
components: {
TextField
},
setup() {
const providedUsername = ref(null);
return { providedUsername };
}
};
</script>
To make the TextField work with the v-model
, all we have to do is update the property and event by replacing the modelValue
with username
:
// TextField.vue
<template>
<input type="text" :value="username" @input="$emit('update:username', $event.target.value)" />
</template>
<script>
export default {
name: "TextField",
props: {
username: {
type: String
}
}
};
</script>
Multiple v-models in one component
Another new feature of Vue 3 is the ability to use multiple v-models
in one component:
// ParentComponent.vue
<template>
<LoginForm v-model:username="providedUsername" v-model:password="providedPassword" />
</template>
<script>
import { ref } from "vue";
import LoginForm from "./LoginForm";
export default {
name: "ParentComponent",
components: {
LoginForm
},
setup() {
const providedUsername = ref(null);
const providedPassword = ref(null);
return { providedUsername, providedPassword };
}
}
</script>
// LoginForm.vue
<template>
<form>
<input type="text" :value="username" @input="$emit('update:username', $event.target.value)" />
<input type="password" :value="password" @input="$emit('update:password', $event.target.value)" />
</form>
</template>
<script>
export default {
name: "TextField",
props: {
username: {
type: String
},
password: {
type: String
}
}
};
</script>
That's it. I hope this article was helpful and now you know how to use the v-model
in Vue 3.
Comments
Anything interesting to share? Write a comment.