Vue.js

Vuejs

Tutorial Vuejs: Binding bidireccional con v-model y defineModel

Aprende a implementar el binding bidireccional en Vue con v-model y defineModel. Optimiza la sincronización de datos en tus componentes y formularios.

Aprende Vuejs GRATIS y certifícate

¿Qué es el Binding Bidireccional?

El binding bidireccional es una característica fundamental de Vue que permite sincronizar automáticamente las propiedades de un componente con los datos del modelo subyacente. Esto significa que cualquier cambio en el valor de una propiedad de entrada se reflejará automáticamente en el modelo de datos, y viceversa. Esta capacidad es particularmente útil para formularios y componentes de entrada de datos, donde la sincronización manual de los datos puede ser tediosa y propensa a errores.

En Vue, el binding bidireccional se implementa principalmente a través de la directiva v-model. Esta directiva se utiliza para crear enlaces reactivos entre los elementos de formulario y los datos del componente. Por ejemplo, en un campo de entrada de texto, el uso de v-model garantiza que cualquier cambio realizado por el usuario en el campo de texto se refleje en el modelo de datos del componente, y cualquier modificación del modelo de datos se actualice en el campo de texto automáticamente.

<template>
  <input v-model="mensaje" placeholder="Escribe algo">
  <p>El mensaje es: {{ mensaje }}</p>
</template>

<script>
export default {
  data() {
    return {
      mensaje: ''
    };
  }
}
</script>

En el ejemplo anterior, el valor del campo de entrada está vinculado bidireccionalmente a la propiedad mensaje del modelo de datos del componente. Cualquier cambio en el campo de entrada actualizará el valor de mensaje, y cualquier cambio en mensaje actualizará el valor del campo de entrada.

El binding bidireccional también se puede aplicar a componentes personalizados. En este caso, v-model se utiliza para vincular una propiedad del componente hijo con una propiedad del componente padre. Para lograr esto, el componente hijo debe emitir un evento específico que notifique al componente padre sobre los cambios en el valor de la propiedad. Por defecto, este evento se llama update:modelValue.

<!-- Componente Padre -->
<template>
  <custom-input v-model="valorPadre"></custom-input>
</template>

<script>
  import CustomInput from './CustomInput.vue';

  export default {
    components: {
      CustomInput
    },
    data() {
      return {
        valorPadre: ''
      };
    }
  }
</script>
<!-- Componente Hijo -->
<template>
  <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)">
</template>

<script>
  export default {
    props: ['modelValue']
  }
</script>

En este ejemplo, el componente CustomInput está diseñado para trabajar con v-model. Se espera que el componente hijo acepte una prop llamada modelValue y emita un evento update:modelValue cuando el valor cambie. Esto permite que el valor del componente padre se actualice automáticamente cuando el usuario interactúa con el componente hijo.

El binding bidireccional es una herramienta poderosa para simplificar la gestión de estados en aplicaciones Vue, especialmente cuando se trabaja con formularios y componentes de entrada de datos.

Uso básico de v-model

El uso de v-model en Vue.js permite crear enlaces bidireccionales entre los datos y los elementos del DOM de manera sencilla y eficiente. La directiva v-model se utiliza principalmente en elementos de formulario como input, textarea y select, así como en componentes personalizados.

Para entender cómo funciona v-model, veamos algunos ejemplos prácticos.

Uso en elementos de formulario nativos:

  1. Input de texto:
<template>
  <input v-model="nombre" placeholder="Introduce tu nombre">
  <p>Nombre: {{ nombre }}</p>
</template>

<script>
  export default {
    data() {
      return {
        nombre: ''
      };
    }
  }
</script>

En este ejemplo, el valor del campo de entrada de texto está vinculado a la propiedad nombre del modelo de datos del componente. Cualquier cambio en el campo de entrada actualizará nombre, y cualquier cambio en nombre se reflejará automáticamente en el campo de entrada.

  1. Textarea:
   <template>
     <textarea v-model="mensaje" placeholder="Escribe un mensaje"></textarea>
     <p>Mensaje: {{ mensaje }}</p>
   </template>

   <script>
   export default {
     data() {
       return {
         mensaje: ''
       };
     }
   }
   </script>

Similar al ejemplo anterior, pero utilizando un textarea. La sincronización bidireccional funciona de la misma manera.

  1. Select:
<template>
  <select v-model="opcionSeleccionada">
    <option disabled value="">Seleccione una opción</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <p>Opción seleccionada: {{ opcionSeleccionada }}</p>
</template>

<script>
  export default {
    data() {
      return {
        opcionSeleccionada: ''
      };
    }
  }
</script>

En este caso, v-model se utiliza con un elemento select. La opción seleccionada está vinculada a la propiedad opcionSeleccionada.

Uso en componentes personalizados:

Para utilizar v-model en componentes personalizados, es necesario realizar algunas configuraciones adicionales. El componente hijo debe aceptar una prop llamada modelValue y emitir un evento update:modelValue cuando el valor cambie.

   <!-- Componente Hijo -->
<template>
  <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)">
</template>

<script>
  export default {
    props: ['modelValue']
  }
</script>
<!-- Componente Padre -->
<template>
  <custom-input v-model="valorPadre"></custom-input>
  <p>Valor en el componente padre: {{ valorPadre }}</p>
</template>

<script>
  import CustomInput from './CustomInput.vue';

  export default {
    components: {
      CustomInput
    },
    data() {
      return {
        valorPadre: ''
      };
    }
  }
</script>

El componente hijo acepta una prop modelValue y emite un evento update:modelValue cuando el valor del input cambia.

En el componente padre, v-model se utiliza para crear un enlace bidireccional entre valorPadre y el componente CustomInput.

Estos ejemplos demuestran cómo v-model facilita la sincronización de datos entre el modelo y la vista, eliminando la necesidad de manejar eventos y actualizaciones manualmente. Esta funcionalidad es esencial para mantener el código limpio y fácil de mantener en aplicaciones Vue.js.

Introducción a defineModel

defineModel es una nueva API introducida en Vue 3.3 que facilita la creación de enlaces bidireccionales entre componentes padre e hijo, similar a v-model, pero con mayor flexibilidad y claridad en la gestión de propiedades y eventos. A diferencia de v-model, defineModel permite definir explícitamente las propiedades y eventos utilizados para el binding bidireccional, proporcionando un control más granular sobre el comportamiento del enlace.

Para utilizar defineModel, primero es necesario definir el modelo en el componente hijo utilizando la función defineModel. Esta función se importa desde vue y se utiliza dentro del setup function del componente hijo.

<!-- Componente Hijo -->
<template>
    <input type="text" v-model="value">
</template>

<script setup>
    const value = defineModel("value");
</script>

En este ejemplo, defineModel se utiliza para crear una propiedad reactiva value. Esto permite que el componente hijo gestione su propio estado y notifique al componente padre sobre los cambios.0

<!-- Componente Padre -->
<template>
  <mi-componente v-model:value="valorPadre" />
  <p>Valor en el componente padre: {{ valorPadre }}</p>
</template>

<script setup lang="ts">
  import { ref } from 'vue';
  import MiComponente from './components/mi-componente.vue';
  
  const valorPadre = ref("");
</script>

En este ejemplo, v-model se utiliza en el componente padre para crear un enlace bidireccional con el componente hijo MiComponente, utilizando la constante valorPadre en el model value referenciandola al argumento, en este caso sólo tenemos uno que es value. De esta manera, cambiará de manera reactiva en cuanto se detecte cualquier cambio en el componente hijo.

defineModel ofrece varias ventajas sobre v-model en términos de flexibilidad y control. Por ejemplo, permite definir múltiples modelos en un mismo componente, lo que es útil cuando se necesita gestionar varios estados de manera independiente.

<!-- Componente Hijo -->
<template>
    <div class="name-container">
        <input v-model="nombre">
        <input v-model="apellido">
    </div>
</template>

<script setup lang="ts">
    const nombre = defineModel('nombre')
    const apellido = defineModel('apellido')
</script>

<style>
    .name-container {
        display: flex;
        flex-direction: column;
        gap: 1em;
    }
</style>
<!-- Componente Padre -->
<template>
  <mi-componente v-model:nombre="nombre" v-model:apellido="apellido" />
  <p>Nombre: {{nombre }}</p>
  <p>Apellido: {{ apellido }}</p>
</template>

<script setup lang="ts">
  import { ref } from 'vue';
  import MiComponente from './components/mi-componente.vue';
  const nombre = ref("");
  const apellido = ref("");
</script>

En este ejemplo, se definen dos modelos separados, nombre y apellido, que permiten gestionar los nombres y apellidos de forma independiente.

En resumen, defineModel proporciona una forma más explícita y flexible de gestionar el binding bidireccional en Vue, permitiendo una mejor organización del código y una mayor claridad en la gestión de propiedades y eventos.

Cuándo usar v-model y cuándo defineModel

La elección entre v-model y defineModel depende del nivel de control y flexibilidad que necesites al crear enlaces bidireccionales en tus componentes Vue.

v-model es la opción más sencilla y directa para la mayoría de los casos, especialmente cuando se trabaja con formularios y componentes de entrada de datos. Su uso es intuitivo y requiere menos configuración, permitiendo una rápida implementación de enlaces bidireccionales. Es ideal para:

  • Elementos de formulario nativos: Como input, textarea y select, donde v-model proporciona una forma rápida y eficiente de sincronizar los datos del modelo con la vista.
  • Componentes personalizados simples: Donde se necesita solo un enlace bidireccional básico. Por ejemplo, un componente de entrada de texto personalizado que solo requiere una prop modelValue y emite un evento update:modelValue.

Sin embargo, v-model tiene limitaciones cuando se requiere un control más granular o se necesitan múltiples enlaces bidireccionales dentro de un mismo componente. Aquí es donde defineModel resulta útil. defineModel permite definir explícitamente las propiedades y eventos utilizados para el binding bidireccional, proporcionando mayor flexibilidad y control. Es adecuado para:

  • Componentes complejos: Donde se necesitan múltiples enlaces bidireccionales. Por ejemplo, un componente de formulario avanzado que maneja varios campos de entrada de manera independiente.
  • Personalización y claridad: Cuando se requiere una configuración más explícita y personalizada de las propiedades y eventos, evitando colisiones y manteniendo el código más organizado.

En resumen, usa v-model para escenarios simples y directos donde la configuración mínima es suficiente, y opta por defineModel cuando necesites un mayor control y flexibilidad sobre las propiedades y eventos de tus componentes.

Aprende Vuejs GRATIS online

Ejercicios de esta lección Binding bidireccional con v-model y defineModel

Evalúa tus conocimientos de esta lección Binding bidireccional con v-model y defineModel con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Todas las lecciones de Vuejs

Accede a todas las lecciones de Vuejs y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Vue Y Su Ecosistema

Vue.js

Introducción Y Entorno

Instalar Y Configurar Vue Con Vite

Vue.js

Introducción Y Entorno

Introducción A La Sintaxis De Plantillas

Vue.js

Componentes

Introducción A Componentes

Vue.js

Componentes

Componentes Con Options Api

Vue.js

Componentes

Componentes Con Composition Api

Vue.js

Componentes

Renderizado Condicional Con V-if

Vue.js

Componentes

Renderizado Iterativo Con V-for

Vue.js

Componentes

Props Y Comunicación Entre Componentes

Vue.js

Componentes

Manejo De Eventos En Vue Con V-on

Vue.js

Componentes

Binding Bidireccional Con V-model Y Definemodel

Vue.js

Componentes

Estilización De Componentes

Vue.js

Componentes

Reactividad Con Ref Y Reactive

Vue.js

Composición Y Reactividad

Ciclo De Vida Con Composition Api

Vue.js

Composición Y Reactividad

Composition Api: Provide E Inject

Vue.js

Composición Y Reactividad

Introducción A Los Composables

Vue.js

Composición Y Reactividad

Uso Avanzado De Composables

Vue.js

Composición Y Reactividad

Introducción A Vue Router

Vue.js

Navegación Y Enrutamiento

Definición Y Manejo De Rutas

Vue.js

Navegación Y Enrutamiento

Rutas Anidadas Y Dinámicas

Vue.js

Navegación Y Enrutamiento

Navegación Programática Y Redirección

Vue.js

Navegación Y Enrutamiento

Solicitudes Http Con Fetch Api

Vue.js

Interacción Http Con Apis De Backend

Solicitudes Http Con Axios

Vue.js

Interacción Http Con Apis De Backend

Introducción A Suspense

Vue.js

Interacción Http Con Apis De Backend

Evaluación Test De Conocimientos Vuejs

Vue.js

Evaluación

Accede GRATIS a Vuejs y certifícate

Certificados de superación de Vuejs

Supera todos los ejercicios de programación del curso de Vuejs y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  1. Comprender el concepto y la importancia del binding bidireccional.
  2. Implementar v-model en elementos de formulario nativos y componentes personalizados.
  3. Configurar enlaces bidireccionales utilizando defineModel en Vue 3.3.
  4. Diferenciar cuándo usar v-model y cuándo defineModel para una mayor flexibilidad y control.