defineProps()

The defineProps() function is used to declare and validate props passed to a component. It's a compile-time macro that enables type checking, setting default values, required props, and custom validation for data passed from parent to child components.

Single or multiple props can be listed in an array or, use the object syntax for prop validation.

It is only available to use inside of <script setup>, and do not need to be imported.

If not using <script setup>, the equivilent is to use the props option inside of export default.

Syntax

// Array syntax
const props = defineProps(['name', 'price', 'inStock']);

// Object syntax
const props = defineProps({
  propName: {
    type: Type,
    required: Boolean,
    default: DefaultValue,
    validator: Function
  }
});

Parameters:

  • Array: An array of strings containing prop names (simple syntax).
  • Object: An object containing prop definitions, each key is a prop name with a value of either:
    • A constructor function (String, Number, Boolean ,Date, Array, Object, Function, or Symbol).
    • An object with the following properties:
      • type: The constructor function (String etc).
      • required: Whether the prop is required (Boolean).
      • default: The props default value or a function that returns the default value.
      • validator: A function that validates the prop.

Basic usage

Here's a simple example of defining props for a product card. This component is passed the three props of name, price, and inStock:

<script setup>
defineProps({
  name: String,
  price: Number,
  inStock: Boolean
});
</script>

<template>
  <div class="product-card">
    <h3>{{ name }}</h3>
    <span>Price: ${{ price }}</span>
    <p>{{ inStock ? 'In Stock' : 'Out of Stock' }}</p>
  </div>
</template>

The props are passed from the parent component:

<template>
  <ProductCard
    name="Pizza oven"
    :price="149.95"
    :inStock="true"
  />
</template>

The v-bind directive (:) is only needed for non-string values. Strings such as name="Pizza oven" don't need v-bind, but numbers (:price="149.95"), variables, booleans (:inStock="true"), arrays, and objects do require it.

Type validation

Vue provides type checking for props. This can be useful to ensure the correct type of data is passed to a component:

defineProps({
  name: String,
  price: Number,
  inStock: Boolean,
  id: [String, Number],
  dateAvailable: Date,
});

Available values of String, Number, Boolean ,Date, Array, Object, Function, or Symbol can be used. As with the id: [String, Number] above, multiple types can also be accepted.

Required props

You can mark any props as required to make sure they are passed by the parent component:

defineProps({
  name: {
    type: String,
    required: true
  },
  price: {
    type: Number,
    required: true
  },
  inStock: {
    type: Boolean,
    required: true
  },
  bestSeller: {
    type: Boolean,
    required: false
  }
});

Default values

Props can have default values when not provided by the parent:

defineProps({
  name: {
    type: String,
    default: 'Coming soon!'
  },
  tags: {
    type: Array,
    default: () => []
  }
});

Custom validation

You can add custom validation using the validator function:

defineProps({
  role: {
    type: String,
    validator: (value) => {
      return ['admin', 'member', 'subscriber'].includes(value);
    }
  },
  points: {
    type: Number,
    validator: (value) => {
      if (value < 100) {
        console.warn('You need 100 points to win a prize.');
        return false;
      }
      return true;
    }
  }
});