Una de las ventajas de los componentes es que se pueden parametrizar, es decir, puedes pasar cierta información a los componentes para que se puedan adaptar dependiendo de las necesidades.

Por ejemplo, cuando creas un input nativo, puedes decidir si lo quieres de tipo text o de tipo password.

<input type="text" /> <input type="password" />

Pues a esto Vue lo llama props. La diferencia con los props nativos es que n Vue puedes pasar de todo: strings, números, booleans, objetos, arrays, etc.

Imagina que quieres crear un componente para mostrar un calendario. Pues puedes crearlo con la idea de poder cambiar el número de filas y columnas que se van a mostrar.

De esta forma podrías hacer algo parecido a esto:

<calendar columns="3" rows="6"></calendar>

Otra cosa brutal de los props es que como pasa con las Variables de Vue también son reactivas, cuando al usar el componente cambies alguno de los valores de los props, automáticamente se actualizará allí donde se referencie.

Los props se pasan desde el componente padre al componente hijo

Cómo se crean los props

Los props los tienes que declarar dentro de la sección props del componente. A diferencia de las variables que declaras dentro del data, aquí no tienes que hacer un return ni tienes que usar una sintaxis rara, directamente declaras el objeto y dentro cada uno de los props.

<script>
export default {
  props: {
    title: String,
  },
};
</script>

Como ves, se declarara el nombre del prop y seguido se pone su tipo.

Los tipos que puedes declarar son:

  • String: Para cadenas de texto.
  • Number: Para números.
  • Boolean: Para booleanos true/false.
  • Array: Listas ya sea de tipos básicos como de objetos.
  • Object: Objetos de javascript.
  • Date: Tipo fecha de javascript.
  • Function: Funciones.
  • Symbol: Símbolos.

Cuando el valor que viene de fuera no coincida con el tipo declarado saltará un error en Vue.

Lo bueno de los props en Vue es que le puedes colocar un valor por defecto en caso de que desde fuera no se pase, para ello el prop lo tienes que crear en forma de Objeto.

<script>
export default {
  props: {
    columns: {
      type: Number,
      default: 4,
    },
    rows: {
      type: Number,
      default: 3,
    },
  },
};
</script>

En el ejemplo anterior si no pasas filas y no pasas columnas se pondrán su valor declarado a default, 4 y 3 en este ejemplo.

También puedes declarar que el prop tiene que ser obligatorio, es decir, desde fuera al usar el componente siempre tendrías que pasar un valor o de lo contrario salta error. Para declarar la obligatoriedad tienes que usar la sintaxis de objeto también y usar la propiedad required.

<script>
export default {
  props: {
    columns: {
      type: Number,
      required: true,
    },
    rows: {
      type: Number,
      default: 3,
    },
  },
};
</script>

El prop para las columnas es obligatorio y por tanto no hace falta poner valor por defecto, porque cuando uses este componente siempre vas a tener que declarar ese valor.

El prop para las filas en este ejemplo no es obligatorio (si no pones required es como si estuviera a false) y por tanto no hace falta que lo pases siempre. Si no se pasa tendrá como valor 3.

Por como está hecho Vue, si quieres poner que el valor por defecto de un prop de tipo array sea array vacío, o quieres que un prop de tipo objeto por defecto sea objeto vacío, tienes que hacer este truquito para la propiedad default.

<script>
export default {
  dates: {
    events: {
      type: Array,
      default: () => [],
    },
    config: {
      type: Object,
      default: () => {},
    },
  },
};
</script>

Mi consejo es que siempre uses la sintaxis de objeto en los props para que todo esté mucho más claro y que siempre declares la propiedad default.

<script>
export default {
  props: {
    // Evita hacer esto
    text: String,

    // Trata de hacer esto
    size: {
      type: Number,
      default: 0,
    },
  },
};
</script>

Cómo usar los props dentro del componente

Los props los tienes que considerar como una variable más del data, es decir, puedes acceder desde cualquier método o computada a los props con el this.

<script>
export default {
  props: {
    columns: {
      type: Number,
      default: 4,
    },
    rows: {
      type: Number,
      default: 3,
    },
  },
  computed: {
    totalCells() {
      return this.columns * this.rows;
    },
  },
};
</script>

Como es lógico, desde la vista también puedes acceder a los props, igual que con las variables del data:

<template>
  <div class="content">
    <p>Rows: {{ rows }}, columns: {{ columns }}</p>
  </div>
</template>
<script>
export default {
  props: {
    columns: {
      type: Number,
      default: 4,
    },
    rows: {
      type: Number,
      default: 3,
    },
  },
  computed: {
    totalMonths() {
      return this.columns * this.rows;
    },
  },
};
</script>

También puedes usar los props dentro de los métodos, incluso dentro de la propiedad created.

<script>
export default {
  props: {
    columns: {
      type: Number,
      default: 4,
    },
    rows: {
      type: Number,
      default: 3,
    },
  },
  created() {
    console.log("Columns: " + this.columns + " Rows: " + this.rows);
  },
};
</script>

Cómo pasar los props al componente

Para usar un componente con props tienes que importarlo como ya vimos, y en la etiqueta tienes que pasar los props como un atributo más del HTML, es decir:

<template>
  <div class="home">
    <calendar :rows="6" :columns="5" />
  </div>
</template>

<script>
// @ es un alias a /src
import Calendar from "@/components/Calendar.vue";

export default {
  components: {
    Calendar,
  },
};
</script>

Como pasa con los Atributos, clases y estilos dinámicos en VueJS de las vistas, por defecto pasas el valor como string.

Para poder pasar números, booleanos, arrays, variables definidas en el data, etc tienes que poner dos puntos antes de la propiedad:

<calendar columns="3" rows="6"></calendar>
<!-- Dentro del componente se reciben los números como string
Por lo tanto dentro del componente no podrías hacer un v-for porque cuenta
como string -->

<calendar :columns="3" :rows="6"></calendar>
<!-- Dentro del componente se reciben los números como números de javascript -->

<calendar :dates="[1,2,4,6,7,9]" :inline="true"></calendar>
<calendar :dates="[1,2,4,6,7,9]" inline></calendar>
<!-- Si quieres pasar un boolean con valor true puedes quitar los puntos
y lo que hay entre comillas para abreviar. Ambas formas son correctas -->

Ejemplo pasando a los props variables definidas en el data:

<template>
  <div class="home">
    <calendar :rows="rows" :columns="columns" />
  </div>
</template>

<script>
// @ es un alias a /src
import Calendar from "@/components/Calendar.vue";

export default {
  components: {
    Calendar,
  },
  data: () => ({
    rows: 6,
    columns: 3,
  }),
};
</script>

Ejemplo pasando propiedades computadas a los props:

<template>
  <div class="home">
    <calendar :text="text" />
  </div>
</template>

<script>
// @ es un alias a /src
import Calendar from "@/components/Calendar.vue";

export default {
  components: {
    Calendar,
  },
  data: () => ({
    rows: 6,
    columns: 3,
  }),
  computed: {
    text() {
      return "Columns: " + this.columns + " Rows: " + this.rows;
    },
  },
};
</script>

Cómo usar los props en el Vue Router

Antes de empezar echa un ojo al El router de Vue para que sepas como funcionan las rutas y el enrutado de Vue.

Los props no solo sirven para para pasar información desde un componente padre a un componente hijo, también puedes pasar props a una ruta cualquiera siempre y cuando estén activados.

Para activar los props en las rutas tienes que poner a true un parámetro especial que tienen las rutas al en el array de rutas que creas al configurar las rutas. Veamos un ejemplo:

router.js

{
  path: "/users",
  name: "users",
  component: Users
  props: true
}

Con eso ya le decimos al vue router que esa ruta puede recibir props desde fuera. Veamos cómo se pasan las rutas al navegar a ellas con vue router.

Para pasar props tan solo tienes que pue pasar un objeto params con los props ya puestos con el valor que quieres por ejemplo.

this.$router.push({ name: "users", params: { title: "test title" } });

En este caso dentro del componente Users hay definido un prop llamado title.

IMPORTANTE. Solo se pueden pasar props a rutas navegando mediante el nombre del componente name. Si decides navegar a una ruta usando su URL, no se podrán pasar props de esta forma.

Conclusiones

Con los props vas a poder hacer componentes genéricos como botones, encabezados, etc que te van a permitir personalizarlos y usarlos en las condiciones que necesites, por ese motivo son muy usados en las librerías de componentes.

En posteriores capítulos veremos el caso contrario, es decir, pasar información desde el componente hijo al componente padre (por ejemplo saber cuando se pulsa un botón en el componente hijo desde el componente padre).