JAVASCRIPT
Creating Custom Two-Way Bindings with `v-model` on Vue 3 Components
Implement custom `v-model` directives on your Vue 3 components to enable powerful two-way data binding, simplifying state management for reusable UI elements.
// components/CustomInput.vue
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
type="text"
class="custom-input"
placeholder="Enter text..."
/>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
defineProps({
modelValue: {
type: String,
default: '',
},
});
defineEmits(['update:modelValue']);
</script>
<style scoped>
.custom-input {
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 1rem;
width: 100%;
max-width: 300px;
}
</style>
<!-- App.vue (example usage) -->
<template>
<div>
<h1>Custom Input Example</h1>
<CustomInput v-model="message" />
<p>Message: {{ message }}</p>
<hr>
<h2>Multiple v-model example (Vue 3.2+)</h2>
<CustomCheckbox v-model:checked="isChecked" v-model:label="checkboxLabel" />
<p>Checkbox State: {{ isChecked ? 'Checked' : 'Unchecked' }}</p>
<p>Checkbox Label: {{ checkboxLabel }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
import CustomInput from './components/CustomInput.vue';
// For the multiple v-model example:
import CustomCheckbox from './components/CustomCheckbox.vue';
const message = ref('Hello Vue!');
const isChecked = ref(true);
const checkboxLabel = ref('Agree to terms');
</script>
<!-- components/CustomCheckbox.vue (for multiple v-model example) -->
<template>
<div>
<input
type="checkbox"
:checked="checked"
@change="$emit('update:checked', $event.target.checked)"
id="custom-checkbox"
/>
<label for="custom-checkbox" @click="$emit('update:label', prompt('Change label:', label) || label)">
{{ label }}
</label>
</div>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
defineProps({
checked: {
type: Boolean,
default: false,
},
label: {
type: String,
default: 'Default Checkbox',
},
});
defineEmits(['update:checked', 'update:label']);
</script>
How it works: This snippet illustrates how to implement custom `v-model` functionality on your own Vue 3 components. By accepting a `modelValue` prop and emitting an `update:modelValue` event, you enable two-way data binding, similar to native form inputs. The example also briefly touches on Vue 3.2+'s ability to define multiple `v-model` bindings with specific argument names, enhancing flexibility for complex components.