JAVASCRIPT
Customizing `v-model` for Complex Components in Vue 3
Extend Vue 3's `v-model` functionality to create custom two-way data bindings for your own components, enabling flexible and intuitive input control.
// src/components/CustomInput.vue
<template>
<div class="custom-input-wrapper">
<label v-if="label">{{ label }}</label>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
type="text"
:placeholder="placeholder"
/>
<p v-if="hint" class="hint-text">{{ hint }}</p>
</div>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
defineProps({
modelValue: String,
label: String,
placeholder: String,
hint: String
});
defineEmits(['update:modelValue']);
</script>
<style scoped>
.custom-input-wrapper {
margin-bottom: 15px;
}
.hint-text {
font-size: 0.8em;
color: #888;
}
</style>
// src/App.vue (or any parent component)
<template>
<div>
<h1>v-model Custom Component Example</h1>
<CustomInput
v-model="userName"
label="Your Name"
placeholder="Enter your name"
hint="This name will be displayed publicly."
/>
<p>Current Name: {{ userName }}</p>
<CustomInput
v-model="userEmail"
label="Your Email"
placeholder="[email protected]"
/>
<p>Current Email: {{ userEmail }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
import CustomInput from './components/CustomInput.vue';
const userName = ref('John Doe');
const userEmail = ref('');
</script>
How it works: Vue 3's `v-model` on a component is syntactic sugar for binding a `modelValue` prop and listening for an `update:modelValue` event. This snippet creates a `CustomInput` component that correctly implements this pattern. The parent component uses `v-model="userName"` and `v-model="userEmail"` to achieve two-way data binding with `CustomInput`, abstracting the underlying prop/event handling. This approach allows for building reusable and robust form controls with standard Vue APIs.