Options API (Vue 2/3)

API de Opciones: Principal en Vue 2/Vue 3


La conocida como «Options API» es la forma tradicional de trabajar con Vue, estando disponible tanto en la versión Vue 2 como en Vue 3. Esta modalidad de API se basa en el uso de un objeto que contiene varias propiedades clave para el funcionamiento de los componentes Vue, como por ejemplo las propiedades props, data, computed, methods, etc...

Vue Options API (Vue 2+)

Cada una de estas opciones permite definir un aspecto clave de Vue, así que vamos a examinar las principales opciones en la siguiente tabla:

Opción Descripción
name Establece un nombre al componente. De lo contrario aparece como "Anónimo" en DevTools.
props / Lista de atributos (props) aceptados desde el componente padre.
data Función que devuelve un con las variables del componente Vue.
computed Lista de funciones que se ejecutarán cuando se acceda a la propiedad en cuestión.
methods Lista de funciones (métodos) disponibles en el componente Vue.
watch Lista de funciones que se disparan cuando detecten cambios en variables con su nombre.
emits / Lista de custom events que pueden ser emitidos desde el componente.

Un componente Vue define su lista de opciones y las exporta mediante el export default, que es la que posteriormente en otros componentes cargaremos mediante import.

Lo que vemos a continuación sería el esqueleto básico de un componente SFC guardado en un fichero .vue. En él definimos un objeto de opciones y lo exportamos para dejarlo preparado para consumir en nuestra colección de componentes:

<template>
  <!-- Código HTML -->
</template>

<script>
export default {
  name: "BaseComponent",
  props: {},
  data() {
    return {}
  },
  computed: {},
  methods: {}
}
</script>

<style>
  /* Estilos CSS */
</style>

En dicho objeto solo hemos insertado las propiedades name, props, data, computed y methods, pero a medida que avancemos en la creación de nuestro componente podremos ir incluyendo las que necesitemos. Vamos a ir explicándolas una por una.

Nombre del componente (name)

La propiedad name permite establecer un nombre al componente. Aunque no sea obligatorio, es una buena práctica establecer siempre un nombre al componente, ya que si estamos utilizando la extensión Vue Dev Tools (Chrome) o Vue Dev Tools (Firefox), en los componentes se nos mostrará el nombre y no Anonymous Component.

Props del componente

Recuerda que el objetivo principal de un componente es prepararlo para ser consumido como una etiqueta HTML y facilitar y simplificar la reutilización de dicho componente. Para ello, lo ideal es pasar parámetros a la etiqueta, que harán más flexible la personalización del componente. Esto se hace a través de los llamados props, que no son más que la información pasada a través de atributos de la etiqueta HTML (nuestro componente):

<BaseComponent id="5" author="Manz" subject="VueJS"></BaseComponent>

Como vemos, desde el HTML del componente podemos pasar los props, pero para recibirlos en el componente debemos definirlos en la opción props. Hay 3 formas principales de hacerlo:

  • Modalidad básica: Con un con el nombre de los props del componente. Es una modalidad poco específica y se recomienda sólo si aún no tenemos bien definido el componente y estamos en una fase de prototipado.
export default {
  props: ["id", "author", "subject"]
}
  • Modalidad avanzada rápida: Con un con los props (clave) y el tipo de dato que se espera de cada uno (valor). Lo recomendable es utilizar como mínimo esta, para así definir un poco más los props de entrada a nuestro componente.
export default {
  props: {
    id: Number,
    author: String,
    subject: String
  }
}
  • Modalidad avanzada: Idem al anterior, pero ofreciendo mucha más información indicando otro con los siguientes parámetros por cada prop:
Parámetro Descripción
type Indica el tipo del prop: String, Number, Boolean, Array, Object, etc...
default Indica el valor por defecto, en el caso de que no se indique la prop en el componente.
required Indica si la prop es obligatoria o no.
validator Comprueba si el valor de la prop es válida o no.

Nuestro ejemplo en esta modalidad quedaría algo parecido a lo siguiente:

export default {
  props: {
    id: {
      type: Number,
      default: 1,
      required: true,
      validator: number => number > 0
    },
    author: {
      type: String,
      required: false
    },
    subject: {
      type: String
      default: "Tema",
      required: true,
    }
  }
}

Observa que el parámetro validator permite definir una función que devolverá true cuando el valor de la prop es correcto y false cuando no pasa la validación y es incorrecto.

Datos o variables (data)

La opción data es un lugar donde Vue guarda todas las variables locales al componente. Esta opción se define como una que devuelve un . Dicho objeto tiene en su interior una colección de propiedades que son las variables de Vue que podremos utilizar en nuestro componente.

En este ejemplo, tenemos las variables nickname, role y life, cada una con su valor correspondiente almacenado. Si quisieramos hacer referencia a alguna de ellas en la parte de templates, simplemente utilizaremos {{ nickname }} (o el nombre de la variable deseada):

<template>
  <div>
    <div>Nick: {{ nickname }} ({{ life }})</div>
    <div>Role: {{ role }}</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      nickname: "Manz",
      role: "Developer",
      life: 99
    }
  }
}
</script>

Más adelante veremos que si queremos hacer referencia a las variables desde la parte de los <script>, hay que hacerlo utilizando la palabra clave this (referencia al objeto de la API). Por ejemplo, this.life devolvería 99, pero sólo desde la parte de Javascript, en los templates seguiríamos usando {{ life }}.

No olvides que la sintaxis de data no debe usarse como una propiedad, sino como una función que devuelve un objeto con las variables en cuestión.

Prop. computadas (computed)

Las propiedades computadas son unas variables precalculadas que puedes reutilizar en Vue sin calcularlas cada vez que las utilices, por lo que pueden ser especialmente interesantes para cálculos u operaciones costosas. Dichas propiedades computadas solo se vuelven a recalcular si detectan que uno de los parámetros implicados cambian, de modo que al calcularse una vez, suele cachear los resultados.

Observa el siguiente ejemplo. Estamos creando una constante (fuera del objeto de opciones de Vue). Luego, en la opción computed creamos una propiedad computada que devuelve esa constante:

<template>
  <div>
    <div>Nick: {{ nickname }} ({{ life }} / {{ TOTAL_LIFE }})</div>
    <div>Role: {{ role }}</div>
  </div>
</template>

<script>
const TOTAL_LIFE = 100;

export default {
  data() {
    return {
      nickname: "Manz",
      role: "Developer",
      life: 99
    }
  },
  computed: {
    TOTAL_LIFE() {
      return TOTAL_LIFE;
    }
  }
}
</script>

Una particularidad de las propiedades computadas es que realmente se definen como funciones, mientras que se utilizan (como se observa en la parte de templates) como variables. En este caso, no estamos usando la propiedad computada para un cálculo complejo o costoso (su utilidad más interesante), sino solo para reflejar el valor de una constante con un ejemplo sencillo y ver como se define.

Sin embargo, en el siguiente ejemplo, si se puede ver un poco mejor la utilidad que podría tener. En este caso se utiliza la variable exp que contiene los años de experiencia, mientras que role pasa a ser una propiedad computada que devuelve un dependiendo de la cantidad de años almacenada en exp:

<template>
  <div>
    <div>Nick: {{ nickname }}</div>
    <div>Role: {{ role }} ({{ exp }} experience years)</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      nickname: "Manz",
      exp: 10,
      life: 99
    }
  },
  computed: {
    role() {
      return this.exp > 12 ? "Expert"
        : this.exp > 8 ? "Senior"
        : this.exp > 4 ? "Middle"
        : "Junior"
    }
  }
}
</script>

Un uso interesante, en vistas de reutilización, suele ser utilizar los props como valores iniciales y almacenar en data los valores actuales del componente. De esta forma se proporciona una forma de indicar valores al componente (a través de props) y luego que sean modificables al usar el componente.

Habrás observado que cuando definimos nombres (en data, props y computed), dichos nombres no se pueden solapar. Vue te obliga a utilizar un buen nombrado de variables en sus propiedades donde, por ejemplo, una prop y una variable en data no se deben llamar igual.

Los métodos (methods)

El apartado methods de las opciones permite añadir funciones en el componente. Al igual que en data guardamos variables de Vue, podemos tener funciones de Vue en methods. Dichas funciones pueden ser utilizadas desde las templates o desde la parte de los scripts, ejecutándolas y obteniendo la información que devuelven.

En el siguiente ejemplo se observa como creamos un <button> que ejecuta la función decLife(), definida en la opción methods. Para preparar el click estamos usando @click, que no es más que el uso de la directiva v-on, la cuál veremos unos capítulos más adelante:

<template>
  <div>
    <div>Nick: {{ nickname }}</div>
    <div>Life: {{ life }}</div>
    <button @click="decLife">Decrement Life</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      nickname: "Manz",
      exp: 10,
      life: 99
    }
  },
  computed: {
    role() {
      return this.exp > 12 ? "Expert"
        : this.exp > 8 ? "Senior"
        : this.exp > 4 ? "Middle"
        : "Junior"
    }
  },
  methods: {
    decLife() {
      this.life--;
    },
  },
}
</script>

Las funciones también podrían ser ejecutadas desde un template con un {{ decLife() }} o desde Javascript, de la forma normal que ejecutamos funciones, siempre teniendo en cuenta que desde Javascript hay que hacerlo de la siguiente forma: this.decLife().

Es importante destacar que las propiedades se actualizan automáticamente como se puede ver de forma muy clara en este ejemplo. La variable life de Vue está modificando su valor al pulsar en el botón que ejecuta el método decLife(), por lo que Vue detecta los cambios con su sistema de reactividad y actualiza todas las partes que dependen de esta variable.

Los observadores (watch)

Las funciones watch son un mecanismo de vigilancia un poco más avanzado de las propiedades computadas (las cuales suelen ser más que suficiente para la mayoría de los casos). A grandes rasgos, los watchers son funciones que colocamos en la propiedad watch y que contendrán funciones que deben coincidir con el nombre de la variable de Vue a vigilar. Si Vue detecta que dicha variable cambia, ejecutará automáticamente la función watch de su mismo nombre.

Estos watchers sólo deben usarse cuando las propiedades calculadas se nos quedan cortas, que suele ser en situaciones en las que necesitamos asincronía o se trata de operaciones muy costosas para cambiar datos.

Hay varias formas de definir un watch:

  • Como una con el mismo nombre de la variable a vigilar.
export default {
  data() {
    return {
      nickname: "Manz",
      life: 99
    }
  },
  watch: {
    life(current, old) {
      console.log(`Valor actual: ${current} Valor anterior: ${old}`);
    }
  }
}
  • Como un con el nombre del método a ejecutar.
export default {
  data() {
    return {
      nickname: "Manz",
      life: 99
    }
  },
  methods: {
    changeLife(newValue) {
      console.log("Se ha detectado cambio de life: ", newValue);
    }
  }
  watch: {
    life: "changeLife"
  }
}
  • Como un con una función handler() con el parámetro deep o immediate, según interese.
Parámetro Por defecto Descripción
deep false La función handler() es ejecutada independientemente de la profundidad del cambio.
immediate false La función handler() es ejecutada inmediatamente después de crearla.
export default {
  data() {
    return {
      nickname: "Manz",
      life: 99
    }
  },
  watch: {
    life: {
      handler(current, old) {
        console.log(`Valor actual: ${current} Valor anterior: ${old}`);
      },
      deep: true
    }
  }
}
  • Como un con varios de los casos anteriores (se ejecutarán todos).

Los emisores (emits)

Como novedad, en Vue 3 se añade la propiedad emits, la cuál permite indicar una lista de eventos personalizados que pueden ser emitidos desde el componente mediante la sintaxis this.$emit("name", value).

Estos eventos personalizados pueden definirse de dos formas diferentes:

  • Modalidad básica: Un de donde simplemente se indican los nombres de los eventos.
export default {
  emits: ["select", "send"]
}
  • Modalidad avanzada: Un que incluye el nombre de los eventos personalizados y una función de validación.
export default {
  emits: {
    select: null,                       /* Sin validación */
    send: data => data.error === false  /* Con validación de parámetros del $emit */
  }
}

Existen otras opciones secundarias en el Options API de Vue, sin embargo, props, data, computed, methods, watch y emits son los principales.

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev