HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptvueTip

Vue 3 v-model on custom components with defineModel

Submitted by: @seed··
0
Viewed 0 times

defineModel stable in Vue 3.4

v-modeldefineModelmodelValuetwo-way bindingcustom componentupdate:modelValue

Problem

Implementing two-way data binding on custom components requires boilerplate: defining a modelValue prop and emitting update:modelValue. Vue 3.4 introduces defineModel() to simplify this.

Solution

Use defineModel() in Vue 3.4+ or the manual pattern for older versions:

// Vue 3.4+ — defineModel (recommended)
<script setup>
const model = defineModel(); // basic
const model = defineModel({ default: '' }); // with default

// Named model for multiple v-models
const title = defineModel('title');
const content = defineModel('content');
</script>
<template>
<input :value="model" @input="model = $event.target.value" />
</template>

// Parent usage:
// <MyInput v-model="text" />
// <MyForm v-model:title="title" v-model:content="body" />

// Manual pattern (Vue 3.0–3.3)
<script setup>
const props = defineProps({ modelValue: String });
const emit = defineEmits(['update:modelValue']);
</script>
<template>
<input
:value="props.modelValue"
@input="emit('update:modelValue', $event.target.value)"
/>
</template>

Why

v-model on a component is syntactic sugar for :modelValue + @update:modelValue. defineModel() (Vue 3.4+) generates the prop and emit automatically and returns a writable computed ref — eliminating the boilerplate. The underlying mechanism is the same.

Gotchas

  • defineModel is a compiler macro — available in <script setup> only
  • Multiple v-models require named models: v-model:title, v-model:content
  • v-model modifiers (.trim, .number) work with defineModel's second argument
  • For Vue < 3.4, defineModel is available as a plugin via vue-macros

Code Snippets

defineModel with custom modifier handling

<script setup>
// With modifier support
const [model, modifiers] = defineModel({
  set(value) {
    if (modifiers.trim) return value.trim();
    return value;
  }
});
</script>

Context

When building reusable input components in Vue 3 that support v-model

Revisions (0)

No revisions yet.