Vue Props
In Vue, parent components pass data to child components through Props. Props are custom attributes you can register on a component. When a value is passed to a prop attribute, it becomes a property of that component instance.
Passing Props
Suppose we have a blog post component BlogPost.vue, and we want to pass the post's title to it from the parent component App.vue.
BlogPost.vue (Child Component)
<script setup>
// Use the defineProps macro to declare props
const props = defineProps(['title'])
// props.title can be accessed in both template and script
console.log(props.title)
</script>
<template>
<h4>{{ title }}</h4>
</template>App.vue (Parent Component)
<script setup>
import BlogPost from './BlogPost.vue'
</script>
<template>
<BlogPost title="My journey with Vue" />
<BlogPost title="Blogging with Vue" />
<BlogPost title="Why Vue is so fun" />
</template>In this example:
- The child component
BlogPost.vueuses thedefineProps(['title'])macro to declare that it receives a prop namedtitle. - The parent component
App.vuepasses a string to thetitleprop when using the<BlogPost>component, similar to passing HTML attributes.
Prop Naming Rules
CamelCase vs. kebab-case: In JavaScript, prop names typically use camelCase, like
greetingText. But in HTML attributes, it's recommended to use kebab-case, likegreeting-text. Vue automatically handles the conversion between these two naming styles.js// In JS defineProps(['greetingText'])html<!-- In HTML --> <MyComponent greeting-text="hello" />
Dynamic Props
Similar to binding normal HTML attributes, we can also use v-bind (or its shorthand :) to dynamically pass props.
<script setup>
import { ref } from 'vue'
import BlogPost from './BlogPost.vue'
const posts = ref([
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
])
</script>
<template>
<BlogPost
v-for="post in posts"
:key="post.id"
:title="post.title"
/>
</template>Prop Validation
Components can specify validation requirements for props, such as type checking. If the passed value doesn't meet the requirements, Vue will give a warning in the browser console.
To specify validation, you can provide an object with validation requirements to defineProps instead of a string array.
<script setup>
defineProps({
// Basic type check
// (`null` and `undefined` will pass any type validation)
propA: Number,
// Multiple possible types
propB: [String, Number],
// Required string
propC: {
type: String,
required: true
},
// Number with default value
propD: {
type: Number,
default: 100
},
// Object with default value
propE: {
type: Object,
// Object or array defaults must be returned from a factory function
default: () => ({ message: 'hello' })
},
// Custom validation function
propF: {
validator: (value) => {
// This value must match one of the following strings
return ['success', 'warning', 'danger'].includes(value)
}
}
})
</script>One-Way Data Flow
All props create a one-way down binding between parent and child props: updates from parent props flow down to child components, but not vice versa. This prevents the child component from accidentally mutating the parent component's state, which would make your application's data flow difficult to understand.
Each time the parent component updates, all props in the child component will refresh to the latest values. This means you should not modify a prop inside a child component. If you do this, Vue will give a warning in the console.