Las props son atributos personalizados que se pueden pasar a un componente hijo desde un componente padre.
Son una forma de comunicación entre componentes (de las más habituales) , en este caso desde exclusívamente de “arriba abajo”.
Las props permiten que el componente hijo reciba datos y los use en su lógica o en su template. Lo cuál nos permite hacer componentes más reusables.
Por ejemplo, imagina que tienes un componente “Tarjeta” que muestra información sobre un producto. Podrías pasarle el nombre del producto y su precio como props, y así reusarlo.
Las props son de solo lectura, lo que significa que el componente hijo no puede modificarlas directamente. Es decir, no sirven para que el componente hijo mande información al padre.
Cómo definir y usar props
Para definir props en un componente hijo, utilizamos la función defineProps
. Esta función devuelve un objeto con las props que el componente puede recibir.
<template>
<div>
<p>Mensaje recibido: {{ message }}</p>
</div>
</template>
<script setup>
// Define las props que el componente puede recibir
const props = defineProps(['title'])
</script>
<template>
<div>
<ChildComponent message="Hola desde el padre" />
</div>
</template>
<script setup>
import ChildComponent from './ChildComponent.vue';
</script>
En este ejemplo:
- El componente padre (
ParentComponent
) pasa la propmessage
al componente hijo (ChildComponent
). - El componente hijo recibe la prop y la muestra en su template.
Props con tipos
Es muy habitual definir el tipo de dato esperado para cada prop. Esto ayuda a evitar errores y mejora la mantenibilidad del código.
<template>
<div>
<p>Nombre: {{ name }}</p>
<p>Edad: {{ age }}</p>
<p>¿Es estudiante?: {{ isStudent ? 'Sí' : 'No' }}</p>
</div>
</template>
<script setup>
const props = defineProps({
name: String, // Prop de tipo String
age: Number, // Prop de tipo Number
isStudent: Boolean, // Prop de tipo Boolean
});
</script>
<template>
<div>
<ChildComponent name="Juan" :age="25" :isStudent="true" />
</div>
</template>
<script setup>
import ChildComponent from './ChildComponent.vue';
</script>
En este ejemplo:
- Se definen props de tipo
String
,Number
yBoolean
. - El componente padre pasa valores específicos para cada prop.
Props con valores por defecto
También es posible definir valores por defecto para las props. En caso de que el componente padre no las proporcione, la prop tendrá el valor por defecto.
<script setup>
const props = defineProps({
name: {
type: String,
default: 'Invitado', // Valor por defecto
},
age: {
type: Number,
default: 18, // Valor por defecto
},
});
</script>
Props requeridas
Es posible marcar una prop como requerida, lo que significa que el componente padre debe proporcionarla.
const props = defineProps({
name: {
type: String,
required: true, // Prop requerida
},
});
Comunicación bidireccional con v-model
Avanzado
Aunque las props son unidireccionales, puedes lograr una comunicación bidireccional usando v-model
.
<template>
<input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
</template>
<script setup>
defineProps({
modelValue: String, // Prop para v-model
});
defineEmits(['update:modelValue']); // Emite el evento para actualizar el valor
</script>
<template>
<div>
<InputComponent v-model="inputValue" />
<p>Valor actual: {{ inputValue }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
import InputComponent from './InputComponent.vue';
const inputValue = ref('');
</script>
En este ejemplo:
- El componente hijo recibe el valor a través de la prop
modelValue
. - El componente hijo emite un evento para actualizar el valor en el componente padre.