Vuejs

Tutorial Vuejs: Componentes con Options API

Vue: Aprende a crear componentes eficientes con Options API. Conoce la estructura, estado, métodos, propiedades computadas y observadores para desarrollar componentes en Vue.

¿Qué es la Options API?

La Options API es una forma de definir componentes en Vue, donde se agrupan distintas opciones dentro de un objeto para describir el comportamiento y la estructura del componente. 

Options API ha sido el enfoque tradicional para crear componentes en las primeras versiones incluyendo Vuejs 2.X. Sin embargo a partir de Vuejs 3.X se recomienda utilizar el nuevo enfoque Composition API ya que es más flexible, utilizando la sintaxis <script setup>

Esta API es especialmente útil para organizar y gestionar el código de manera modular y legible. En la Options API, se utilizan propiedades específicas del objeto del componente como data, methods, computed, watch, entre otras, para definir el estado y el comportamiento del componente.

Un ejemplo básico de un componente utilizando la Options API es el siguiente:

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="updateMessage">Actualizar Mensaje</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hola, Vue!'
    };
  },
  methods: {
    updateMessage() {
      this.message = 'Mensaje actualizado';
    }
  }
};
</script>

En este ejemplo, el objeto exportado define un componente con:

  • data: Una función que devuelve un objeto con el estado local del componente. En este caso, message es una propiedad del estado.
  • methods: Un objeto que contiene funciones que pueden ser llamadas desde el template. Aquí, updateMessage es un método que actualiza la propiedad message.

La Options API permite una clara separación de las distintas partes del componente, facilitando la comprensión y el mantenimiento del código. Cada sección del componente, como el estado, los métodos, las propiedades computadas, y los observadores, se definen en su correspondiente opción dentro del objeto del componente.

Además, la Options API es compatible con herramientas y bibliotecas auxiliares de Vue, lo que facilita la integración y la extensión de las funcionalidades del componente. Por ejemplo, Vue Router y Vuex se integran sin problemas utilizando la Options API.

En resumen, la Options API proporciona una estructura organizada y modular para definir componentes en Vue, agrupando opciones específicas dentro de un objeto para describir el comportamiento y la estructura del componente.

Estructura Básica de un Componente con Options API

En Vue, un componente definido con la Options API se estructura en varias secciones dentro de un objeto exportado. A continuación, se detalla la estructura básica de un componente utilizando la Options API, destacando las principales opciones que se pueden definir:

template: Define la estructura HTML del componente. Generalmente, se escribe en una etiqueta <template> en archivos .vue.

script: Contiene el objeto de configuración del componente, donde se definen las opciones como data, methods, computed, watch, entre otras. Se encapsula dentro de una etiqueta <script>.

style: Permite definir los estilos CSS específicos para el componente. Se coloca dentro de una etiqueta <style> y puede ser scoped para que los estilos no afecten a otros componentes.

Ejemplo básico de un componente con una estructura completa:

<template>
  <div>
    <h1>{{ title }}</h1>
    <p>{{ description }}</p>
    <button @click="changeTitle">Cambiar Título</button>
  </div>
</template>

<script>
export default {
  name: 'MiComponente', // Nombre del componente
  data() {
    return {
      title: 'Título Inicial',
      description: 'Descripción del componente.'
    };
  },
  methods: {
    changeTitle() {
      this.title = 'Título Cambiado';
    }
  }
};
</script>

<style scoped>
h1 {
  color: blue;
}
p {
  font-size: 18px;
}
</style>

En este ejemplo, se observa lo siguiente:

  • name: Define el nombre del componente. Es útil para la depuración y cuando se registran componentes de manera global.
  • data: Una función que retorna un objeto con el estado local del componente. Aquí se definen las propiedades title y description.
  • methods: Un objeto que contiene funciones que pueden ser invocadas desde el template. En este caso, changeTitle es un método que actualiza la propiedad title.

Otras opciones comunes y avanzadas que se pueden incluir en la estructura del componente son:

  • props: Define las propiedades que el componente acepta desde su componente padre.
  • computed: Permite definir propiedades computadas que dependen de otras propiedades del estado.
  • watch: Permite observar y reaccionar a cambios en propiedades específicas del estado.
  • lifecycle hooks: Métodos que se ejecutan en diferentes etapas del ciclo de vida del componente, como created, mounted, updated, y destroyed.

Ejemplo de un componente utilizando props y lifecycle hooks:

<template>
  <div>
    <h1>{{ title }}</h1>
    <p>{{ computedDescription }}</p>
  </div>
</template>

<script>
export default {
  name: 'MiComponenteAvanzado',
  props: {
    initialTitle: {
      type: String,
      required: true
    }
  },
  data() {
    return {
      title: this.initialTitle,
      description: 'Descripción avanzada del componente.'
    };
  },
  computed: {
    computedDescription() {
      return this.description.toUpperCase();
    }
  },
  watch: {
    title(newTitle, oldTitle) {
      console.log(`El título cambió de ${oldTitle} a ${newTitle}`);
    }
  },
  created() {
    console.log('El componente ha sido creado');
  },
  methods: {
    updateTitle(newTitle) {
      this.title = newTitle;
    }
  }
};
</script>

<style scoped>
h1 {
  color: green;
}
p {
  font-style: italic;
}
</style>

En este ejemplo avanzado, se añaden:

  • props: initialTitle se define como una propiedad que debe ser pasada al componente.
  • computed: computedDescription es una propiedad computada que transforma description.
  • watch: Observa cambios en la propiedad title y ejecuta una función cuando esta cambia.
  • created: Un lifecycle hook que se ejecuta cuando el componente es creado.

Esta estructura modular y organizada facilita la gestión y el mantenimiento de los componentes en aplicaciones Vue, permitiendo un desarrollo más eficiente y claro.

Definición del Estado con data

En Vue, la definición del estado de un componente se realiza a través de la opción data en la Options API. Esta opción es una función que retorna un objeto, el cual contiene las propiedades reactivas que representan el estado local del componente. Cada vez que una de estas propiedades cambia, Vue se encarga de actualizar la vista para reflejar el nuevo estado.

Para definir el estado con data, se sigue la siguiente estructura:

export default {
  data() {
    return {
      propiedad1: valorInicial1,
      propiedad2: valorInicial2,
      // más propiedades de estado
    };
  }
};

La función data debe retornar un nuevo objeto cada vez que se instancia el componente, asegurando así que cada instancia del componente tenga su propio estado independiente. A continuación, se presenta un ejemplo práctico:

<template>
  <div>
    <h1>{{ titulo }}</h1>
    <p>{{ mensaje }}</p>
    <button @click="actualizarMensaje">Actualizar Mensaje</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      titulo: 'Bienvenido a Vue',
      mensaje: 'Este es el estado inicial'
    };
  },
  methods: {
    actualizarMensaje() {
      this.mensaje = 'El estado ha sido actualizado';
    }
  }
};
</script>

<style scoped>
h1 {
  color: navy;
}
p {
  font-size: 16px;
}
</style>

En este ejemplo, el componente define dos propiedades de estado: titulo y mensaje. La propiedad titulo contiene un valor estático, mientras que mensaje se puede actualizar mediante el método actualizarMensaje.

Es importante notar que Vue hace que todas las propiedades definidas en data sean reactivas. Esto significa que cualquier cambio en estas propiedades desencadenará una actualización automática de la interfaz de usuario donde se utilicen. Por ejemplo, en el template, {{ mensaje }} se actualizará automáticamente cuando mensaje cambie de valor.

Además, se pueden definir propiedades complejas como arrays y objetos dentro de data. Sin embargo, es crucial recordar que debido a la naturaleza reactiva de Vue, las modificaciones directas a estos arrays y objetos se reflejan automáticamente en la vista. Aquí hay un ejemplo que incluye un array y un objeto en el estado:

<template>
  <div>
    <ul>
      <li v-for="item in items" :key="item.id">{{ item.name }}</li>
    </ul>
    <button @click="agregarItem">Agregar Item</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' }
      ],
      nuevoItem: { id: 3, name: 'Item 3' }
    };
  },
  methods: {
    agregarItem() {
      this.items.push(this.nuevoItem);
      this.nuevoItem = { id: this.nuevoItem.id + 1, name: `Item ${this.nuevoItem.id + 1}` };
    }
  }
};
</script>

<style scoped>
ul {
  list-style-type: none;
}
li {
  font-size: 14px;
}
</style>

En este ejemplo, items es un array de objetos y nuevoItem es un objeto que representa el nuevo elemento que se agregará al array. El método agregarItem añade nuevoItem al array items y actualiza nuevoItem para el siguiente elemento.

Utilizar data para definir el estado del componente es fundamental en la Options API de Vue, ya que permite gestionar de manera eficiente y clara el estado local, facilitando la reactividad y la actualización automática de la interfaz de usuario.

Definición de Métodos con methods

En Vue, los métodos se definen utilizando la opción methods dentro del objeto del componente en la Options API. Esta opción es un objeto que contiene funciones que pueden ser invocadas desde el template del componente o desde otros métodos y propiedades computadas dentro del mismo componente. Los métodos son útiles para manejar eventos, realizar cálculos y manipular el estado del componente.

Para definir métodos en un componente, se sigue la siguiente estructura:

export default {
  methods: {
    nombreDelMetodo() {
      // lógica del método
    }
  }
};

Cada función dentro del objeto methods puede acceder al contexto del componente a través de this, lo que permite manipular el estado y llamar a otros métodos del componente. A continuación, se presenta un ejemplo práctico que ilustra cómo definir y utilizar métodos en un componente Vue:

<template>
  <div>
    <h1>{{ titulo }}</h1>
    <button @click="cambiarTitulo">Cambiar Título</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      titulo: 'Título Inicial'
    };
  },
  methods: {
    cambiarTitulo() {
      this.titulo = 'Título Cambiado';
    }
  }
};
</script>

<style scoped>
h1 {
  color: darkgreen;
}
button {
  padding: 10px;
  font-size: 16px;
}
</style>

En este ejemplo, el método cambiarTitulo se define dentro de methods y se utiliza en el template a través del evento click del botón. Cuando el botón es clicado, el método se ejecuta y actualiza la propiedad titulo del estado del componente.

Es recomendable seguir algunas buenas prácticas al definir métodos en Vue:

  • Mantenibilidad: Cada método debe tener una única responsabilidad. Esto facilita la lectura y el mantenimiento del código.
  • Nombres Claros: Utiliza nombres descriptivos para los métodos que indiquen claramente su propósito.
  • Reutilización: Si un método se utiliza en múltiples componentes, considera moverlo a un mixin o a un archivo de utilidades para promover la reutilización del código.

Además, los métodos pueden ser utilizados junto con otras opciones de la Options API, como computed y watch, para crear una lógica más compleja y reactiva. A continuación, se muestra un ejemplo avanzado que combina métodos con propiedades computadas y observadores:

<template>
  <div>
    <h1>{{ titulo }}</h1>
    <p>{{ descripcion }}</p>
    <button @click="actualizarTitulo">Actualizar Título</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      titulo: 'Título Original',
      contador: 0
    };
  },
  computed: {
    descripcion() {
      return `El contador está en ${this.contador}`;
    }
  },
  watch: {
    contador(nuevoValor) {
      if (nuevoValor > 5) {
        this.resetearContador();
      }
    }
  },
  methods: {
    actualizarTitulo() {
      this.titulo = 'Título Actualizado';
      this.incrementarContador();
    },
    incrementarContador() {
      this.contador++;
    },
    resetearContador() {
      this.contador = 0;
    }
  }
};
</script>

<style scoped>
h1 {
  color: darkred;
}
button {
  padding: 10px;
  font-size: 16px;
}
</style>

En este ejemplo, el método actualizarTitulo actualiza la propiedad titulo y llama a otro método incrementarContador para incrementar el valor del contador. La propiedad computada descripcion depende del valor de contador y se actualiza automáticamente cuando este cambia. Además, el observador contador vigila los cambios en el valor de contador y llama al método resetearContador cuando el valor supera 5.

Definir métodos en Vue utilizando la opción methods en la Options API es una práctica fundamental para manejar la lógica y los eventos dentro de los componentes. Esta capacidad de organizar y estructurar el código en métodos claramente definidos mejora la mantenibilidad y la legibilidad del código, permitiendo el desarrollo de aplicaciones Vue de manera eficiente y modular.

Propiedades computed

En Vue, las propiedades computed se utilizan para declarar propiedades que dependen de otras propiedades del estado y que, cuando estas cambian, se vuelven a calcular automáticamente. A diferencia de los métodos, las propiedades computed son cacheadas basándose en sus dependencias reactivas. Solo se recalcularán cuando una de sus dependencias cambie, lo que las hace eficientes para operaciones costosas.

Para definir una propiedad computed en un componente utilizando la Options API, se sigue la siguiente estructura:

export default {
  data() {
    return {
      base: 10,
      altura: 5
    };
  },
  computed: {
    area() {
      return this.base * this.altura;
    }
  }
};

En este ejemplo, area es una propiedad computed que depende de base y altura. Siempre que base o altura cambien, area será recalculada.

Las propiedades computed son útiles para:

  1. Lógica Derivada: Calcular valores basados en otras propiedades del estado.
  2. Formateo de Datos: Transformar o formatear datos para mostrarlos en la vista.
  3. Optimización: Evitar cálculos innecesarios al cachear resultados.

Ejemplo práctico de uso:

<template>
  <div>
    <p>Base: {{ base }}</p>
    <p>Altura: {{ altura }}</p>
    <p>Área: {{ area }}</p>
    <button @click="incrementarBase">Incrementar Base</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      base: 10,
      altura: 5
    };
  },
  computed: {
    area() {
      return this.base * this.altura;
    }
  },
  methods: {
    incrementarBase() {
      this.base++;
    }
  }
};
</script>

<style scoped>
p {
  font-size: 16px;
}
button {
  margin-top: 10px;
  padding: 5px;
}
</style>

En este ejemplo, area es una propiedad computada que calcula el área de un rectángulo basado en base y altura. La propiedad area se actualiza automáticamente cuando base cambia al hacer clic en el botón "Incrementar Base".

Las propiedades computed también pueden tener setters, permitiendo que se comporten como propiedades de dos vías. Esto es útil para casos donde se necesita una transformación inversa. Ejemplo con setter:

export default {
  data() {
    return {
      firstName: 'John',
      lastName: 'Doe'
    };
  },
  computed: {
    fullName: {
      get() {
        return `${this.firstName} ${this.lastName}`;
      },
      set(newValue) {
        const names = newValue.split(' ');
        this.firstName = names[0];
        this.lastName = names[names.length - 1];
      }
    }
  }
};

En este ejemplo, fullName es una propiedad computada con un getter y un setter. El getter concatena firstName y lastName, mientras que el setter divide un nombre completo en firstName y lastName.

Las propiedades computed son una herramienta poderosa dentro de la Options API de Vue, permitiendo crear lógica derivada de manera eficiente y reactiva. Utilizar propiedades computed mejora la organización del código y puede optimizar el rendimiento de la aplicación al evitar cálculos innecesarios.

Observadores con watch

En Vue, los observadores (watch) se utilizan para realizar acciones en respuesta a cambios en las propiedades del estado del componente. A diferencia de las propiedades computadas, que son principalmente para cálculos derivados, los observadores permiten ejecutar lógica personalizada cuando cambian los valores observados, lo que es útil para tareas asíncronas o efectos secundarios que no deben ser realizados dentro de una propiedad computada.

Para definir un observador en un componente utilizando la Options API, se utiliza la opción watch, que es un objeto donde las claves son los nombres de las propiedades a observar y los valores son las funciones que reaccionan a los cambios. La estructura básica es la siguiente:

export default {
  data() {
    return {
      valor: 0
    };
  },
  watch: {
    valor(nuevoValor, valorAnterior) {
      // lógica a ejecutar cuando 'valor' cambia
    }
  }
};

En este ejemplo, el observador valor se ejecuta cada vez que la propiedad valor cambia, recibiendo el nuevo valor y el valor anterior como argumentos.

Los observadores son útiles para:

  1. Tareas Asíncronas: Realizar llamadas a APIs o ejecutar lógica compleja que no debe estar en una propiedad computada.
  2. Validación de Datos: Validar entradas del usuario en tiempo real.
  3. Efectos Secundarios: Ejecutar efectos que dependen de cambios en el estado, como animaciones o manipulaciones del DOM.

Ejemplo práctico con una llamada a una API:

<template>
  <div>
    <input v-model="busqueda" placeholder="Buscar...">
    <ul>
      <li v-for="resultado in resultados" :key="resultado.id">{{ resultado.nombre }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      busqueda: '',
      resultados: []
    };
  },
  watch: {
    busqueda(nuevaBusqueda) {
      this.obtenerResultados(nuevaBusqueda);
    }
  },
  methods: {
    async obtenerResultados(termino) {
      if (termino) {
        const respuesta = await fetch(`https://api.ejemplo.com/buscar?q=${termino}`);
        this.resultados = await respuesta.json();
      } else {
        this.resultados = [];
      }
    }
  }
};
</script>

<style scoped>
input {
  margin-bottom: 10px;
  padding: 5px;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  font-size: 14px;
}
</style>

En este ejemplo, el observador busqueda se ejecuta cada vez que cambia el valor del campo de entrada. Llama al método obtenerResultados que realiza una llamada a una API y actualiza la lista de resultados.

Además de observar propiedades simples, los observadores pueden ser configurados para observar objetos anidados y arrays utilizando la opción deep. También pueden ser configurados para ejecutarse inmediatamente la primera vez que se definen utilizando la opción immediate.

Ejemplo de observador profundo (deep):

export default {
  data() {
    return {
      usuario: {
        nombre: 'Juan',
        edad: 25
      }
    };
  },
  watch: {
    usuario: {
      handler(nuevoUsuario) {
        console.log('El usuario ha cambiado:', nuevoUsuario);
      },
      deep: true
    }
  }
};

En este ejemplo, el observador usuario se ejecuta cada vez que cualquier propiedad dentro del objeto usuario cambia, gracias a la opción deep.

Ejemplo de observador inmediato (immediate):

export default {
  data() {
    return {
      contador: 0
    };
  },
  watch: {
    contador: {
      handler(nuevoValor) {
        console.log('El contador ha cambiado:', nuevoValor);
      },
      immediate: true
    }
  }
};

En este ejemplo, el observador contador se ejecuta inmediatamente después de ser definido, además de cada vez que contador cambia, gracias a la opción immediate.

Los observadores en Vue son una herramienta fundamental para reaccionar a cambios en el estado del componente y ejecutar lógica personalizada en respuesta a estos cambios. Utilizarlos de manera efectiva permite manejar tareas asíncronas, validaciones y efectos secundarios de forma organizada y reactiva.

Certifícate en Vuejs con CertiDevs PLUS

Ejercicios de esta lección Componentes con Options API

Evalúa tus conocimientos de esta lección Componentes con Options API 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.

En esta lección

Objetivos de aprendizaje de esta lección

  1. Comprender la Options API en Vue para la definición de componentes.
  2. Aprender a estructurar un componente utilizando data, methods, computed, y watch.
  3. Implementar propiedades computadas y observadores reactivos.
  4. Crear componentes modulares y mantenibles.
  5. Integrar Vue con herramientas adicionales como Vue Router y Vuex.