¿Qué es defineModel()?
Es una macro especial disponible únicamente en el contexto de <script setup>. Nos permite declarar una prop reactiva que está automáticamente conectada con el v-model del componente padre.
En resumen: menos código, menos errores, más claridad.
Ejemplo básico: Un input personalizado
<!-- CustomInput.vue -->
<script setup lang="ts">
const model = defineModel({ type: String })
</script>
<template>
<input v-model="model" placeholder="Escribe algo..." />
</template>Y lo usas así:
<!-- ParentComponent.vue -->
<script setup lang="ts">
const nombre = ref('')
</script>
<template>
<CustomInput v-model="nombre" />
</template>Automáticamente:
Se declara la
prop modelValueSe emite
update:modelValueal cambiar¡No necesitas escribir props ni emits manualmente!
Múltiples v-models: ¿Y si quiero algo más que modelValue?
Fácil. Solo le das un nombre:
<!-- CounterComponent.vue -->
<script setup lang="ts">
const count = defineModel('count', { type: Number, default: 0 })
function incrementar() {
count.value++
}
</script>
<template>
<button @click="incrementar">Contador: {{ count }}</button>
</template>En el padre:
<!-- ParentComponent.vue -->
<script setup lang="ts">
const clicks = ref(5)
</script>
<template>
<Counter v-model:count="clicks" />
</template>Cuidado con los valores por defecto
Un error común: declarar un valor por defecto en el hijo, pero no pasar nada desde el padre. Esto puede causar desincronización.
Consejo: si vas a usar
default, asegúrate de manejar correctamente el valor inicial desde el padre, o usar una sincronización manual si es necesario.
¿Y los modificadores? .trim, .number, .lazy...
Sí, también funcionan. Se puede capturar y personalizar su comportamiento:
<script setup lang="ts">
const [texto, modifiers] = defineModel()
const [modelValue, modelModifiers] = defineModel({
set(value) {
if (modelModifiers.trim) {
return value.trim()
}
return value
}
})
</script>Ahora en el padre:
<MyInput v-model.trim="mensaje" />El
set()se encarga de aplicar.trimantes de enviar el valor modificado al padre.
Conclusión
defineModel() es un game changer para quienes usamos <script setup> en Vue 3.4+. Hace que trabajar con v-model en componentes sea más natural, más limpio y menos propenso a errores. Es ideal tanto para componentes simples como para interfaces complejas con múltiples bindings.
Sigue leyendo
Una idea lleva a otra.
)
¿Cómo usar defineExpose?
)
¿Cómo integrar Tailwind 4 en Vue.js 3 + Vite?
)
)