Vue Component Props
By Flavio Copes
Learn how Vue 3 props pass data from parent to child, including defineProps, types, defaults, required props, and camelCase vs kebab-case in templates.
- Define a prop inside the component
- Accept multiple props
- Set the prop type
- Set a prop to be mandatory
- Set the default value of a prop
- Passing props to the component
Define a prop inside the component
Props are how a child component receives data from its parent.
Declare them before you use them.
With <script setup> and defineProps (the usual Vue 3 style in SFCs):
<template>
<p>Hi {{ name }}</p>
</template>
<script setup>
defineProps(['name'])
</script>
With the Options API:
<template>
<p>Hi {{ name }}</p>
</template>
<script>
export default {
props: ['name']
}
</script>
Or when you register a component on the app:
import { createApp } from 'vue'
const app = createApp({})
app.component('UserName', {
props: ['name'],
template: '<p>Hi {{ name }}</p>'
})
app.mount('#app')
Accept multiple props
List every prop you expect:
defineProps(['firstName', 'lastName'])
export default {
props: ['firstName', 'lastName']
}
Set the prop type
Use an object form to declare types:
defineProps({
firstName: String,
lastName: String
})
Valid types:
- String
- Number
- Boolean
- Array
- Object
- Date
- Function
- Symbol
In development, Vue warns when the runtime type does not match.
Allow more than one type:
defineProps({
firstName: [String, Number]
})
Set a prop to be mandatory
defineProps({
firstName: {
type: String,
required: true
}
})
Set the default value of a prop
defineProps({
firstName: {
type: String,
default: 'Unknown person'
}
})
For objects and arrays, default must be a factory function. Otherwise every instance would share the same reference:
defineProps({
name: {
type: Object,
default() {
return {
firstName: 'Unknown',
lastName: ''
}
}
}
})
You can also write a custom validator:
defineProps({
name: {
validator(value) {
return value === 'Flavio'
}
}
})
Passing props to the component
Static string:
<UserName name="Flavio" />
From parent state, use v-bind / ::
<template>
<UserName :name="name" />
</template>
<script setup>
import { ref } from 'vue'
import UserName from './UserName.vue'
const name = ref('Flavio')
</script>
In JavaScript, prop names are camelCase (firstName). In DOM templates, use kebab-case (first-name). Vue maps them:
<UserName first-name="Flavio" last-name="Copes" />
defineProps({
firstName: String,
lastName: String
})
In Single File Component templates (compiled), camelCase in the template is fine too.
Props are one-way: parent to child. When the parent updates the prop, the child sees the new value. Do not mutate a prop inside the child. Emit an event, or use a local copy, if the child needs to request a change. More on that in component communication.
You can use an expression when binding:
<ColorBox :colored="color === 'white'" />Want me to talk about your product? You can sponsor this site.