# Props {#props} > This page assumes you've already read the [Components Basics](/guide/essentials/component-basics). Read that first if you are new to components.
## Props Declaration {#props-declaration} Vue components require explicit props declaration so that Vue knows what external props passed to the component should be treated as fallthrough attributes (which will be discussed in [its dedicated section](/guide/components/attrs)).
In SFCs using ` ``` In non-` ``` More details: [Typing Component Props](/guide/typescript/composition-api#typing-component-props)
## Prop Passing Details {#prop-passing-details} ### Prop Name Casing {#prop-name-casing} We declare long prop names using camelCase because this avoids having to use quotes when using them as property keys, and allows us to reference them directly in template expressions because they are valid JavaScript identifiers:
```js defineProps({ greetingMessage: String }) ```
```js export default { props: { greetingMessage: String } } ```
```vue-html {{ greetingMessage }} ``` Technically, you can also use camelCase when passing props to a child component (except in [in-DOM templates](/guide/essentials/component-basics#in-dom-template-parsing-caveats)). However, the convention is using kebab-case in all cases to align with HTML attributes: ```vue-html ``` We use [PascalCase for component tags](/guide/components/registration#component-name-casing) when possible because it improves template readability by differentiating Vue components from native elements. However, there isn't as much practical benefit in using camelCase when passing props, so we choose to follow each language's conventions. ### Static vs. Dynamic Props {#static-vs-dynamic-props} So far, you've seen props passed as static values, like in: ```vue-html ``` You've also seen props assigned dynamically with `v-bind` or its `:` shortcut, such as in: ```vue-html ``` ### Passing Different Value Types {#passing-different-value-types} In the two examples above, we happen to pass string values, but _any_ type of value can be passed to a prop. #### Number {#number} ```vue-html ``` #### Boolean {#boolean} ```vue-html ``` #### Array {#array} ```vue-html ``` #### Object {#object} ```vue-html ``` ### Binding Multiple Properties Using an Object {#binding-multiple-properties-using-an-object} If you want to pass all the properties of an object as props, you can use [`v-bind` without an argument](/guide/essentials/template-syntax#dynamically-binding-multiple-attributes) (`v-bind` instead of `:prop-name`). For example, given a `post` object:
```js export default { data() { return { post: { id: 1, title: 'My Journey with Vue' } } } } ```
```js const post = { id: 1, title: 'My Journey with Vue' } ```
The following template: ```vue-html ``` Will be equivalent to: ```vue-html ``` ## One-Way Data Flow {#one-way-data-flow} All props form a **one-way-down binding** between the child property and the parent one: when the parent property updates, it will flow down to the child, but not the other way around. This prevents child components from accidentally mutating the parent's state, which can make your app's data flow harder to understand. In addition, every time the parent component is updated, all props in the child component will be refreshed with the latest value. This means you should **not** attempt to mutate a prop inside a child component. If you do, Vue will warn you in the console:
```js const props = defineProps(['foo']) // ❌ warning, props are readonly! props.foo = 'bar' ```
```js export default { props: ['foo'], created() { // ❌ warning, props are readonly! this.foo = 'bar' } } ```
There are usually two cases where it's tempting to mutate a prop: 1. **The prop is used to pass in an initial value; the child component wants to use it as a local data property afterwards.** In this case, it's best to define a local data property that uses the prop as its initial value:
```js const props = defineProps(['initialCounter']) // counter only uses props.initialCounter as the initial value; // it is disconnected from future prop updates. const counter = ref(props.initialCounter) ```
```js export default { props: ['initialCounter'], data() { return { // counter only uses this.initialCounter as the initial value; // it is disconnected from future prop updates. counter: this.initialCounter } } } ```
2. **The prop is passed in as a raw value that needs to be transformed.** In this case, it's best to define a computed property using the prop's value:
```js const props = defineProps(['size']) // computed property that auto-updates when the prop changes const normalizedSize = computed(() => props.size.trim().toLowerCase()) ```
```js export default { props: ['size'], computed: { // computed property that auto-updates when the prop changes normalizedSize() { return this.size.trim().toLowerCase() } } } ```
### Mutating Object / Array Props {#mutating-object-array-props} When objects and arrays are passed as props, while the child component cannot mutate the prop binding, it **will** be able to mutate the object or array's nested properties. This is because in JavaScript objects and arrays are passed by reference, and it is unreasonably expensive for Vue to prevent such mutations. The main drawback of such mutations is that it allows the child component to affect parent state in a way that isn't obvious to the parent component, potentially making it more difficult to reason about the data flow in the future. As a best practice, you should avoid such mutations unless the parent and child are tightly coupled by design. In most cases, the child should [emit an event](/guide/components/events) to let the parent perform the mutation. ## Prop Validation {#prop-validation} Components can specify requirements for their props, such as the types you've already seen. If a requirement is not met, Vue will warn you in the browser's JavaScript console. This is especially useful when developing a component that is intended to be used by others. To specify prop validations, you can provide an object with validation requirements to the `defineProps()` macro`props` option, instead of an array of strings. For example:
```js defineProps({ // Basic type check // (`null` and `undefined` values will allow any type) propA: Number, // Multiple possible types propB: [String, Number], // Required string propC: { type: String, required: true }, // Required but nullable string propD: { type: [String, null], required: true }, // Number with a default value propE: { type: Number, default: 100 }, // Object with a default value propF: { type: Object, // Object or array defaults must be returned from // a factory function. The function receives the raw // props received by the component as the argument. default(rawProps) { return { message: 'hello' } } }, // Custom validator function // full props passed as 2nd argument in 3.4+ propG: { validator(value, props) { // The value must match one of these strings return ['success', 'warning', 'danger'].includes(value) } }, // Function with a default value propH: { type: Function, // Unlike object or array default, this is not a factory // function - this is a function to serve as a default value default() { return 'Default function' } } }) ``` :::tip Code inside the `defineProps()` argument **cannot access other variables declared in `