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...
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 |
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
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 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
ycomputed
), dichos nombres no se pueden solapar. Vue te obliga a utilizar un buen nombrado de variables en sus propiedades donde, por ejemplo, unaprop
y una variable endata
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étododecLife()
, 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ámetrodeep
oimmediate
, 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.