Files
gt-agent-company/.agents/skills/vue/references/components-props.md
sexygoat 3c62cc1cd1 first
2026-03-31 18:41:52 +08:00

3.7 KiB

name, description
name description
component-props Declare and use props with type safety and validation

Component Props

Props are custom attributes for passing data from parent to child components.

Use TypeScript interfaces with defineProps:

<script setup lang="ts">
interface Props {
  title: string
  count?: number
  items: string[]
}

const props = defineProps<Props>()
</script>

Reactive Props Destructure (3.5+)

Destructure props while keeping reactivity:

<script setup lang="ts">
interface Props {
  msg?: string
  count?: number
}

const { msg = 'hello', count = 0 } = defineProps<Props>()

// Both msg and count are reactive
watchEffect(() => {
  console.log(msg, count)
})
</script>

Passing destructured props to functions

const { foo } = defineProps(['foo'])

// ❌ Won't work - passes value not reactive source
watch(foo, /* ... */)

// ✅ Wrap in getter
watch(() => foo, /* ... */)

// ✅ For composables
useComposable(() => foo)

Default Values with withDefaults (3.4 and below)

<script setup lang="ts">
interface Props {
  msg?: string
  labels?: string[]
}

const props = withDefaults(defineProps<Props>(), {
  msg: 'hello',
  labels: () => ['one', 'two'] // Factory function for objects/arrays
})
</script>

Runtime Declaration

For runtime validation without TypeScript:

<script setup lang="ts">
const props = defineProps({
  // Basic type check
  propA: Number,
  // Multiple types
  propB: [String, Number],
  // Required
  propC: { type: String, required: true },
  // With default
  propD: { type: Number, default: 100 },
  // Object with factory default
  propE: {
    type: Object,
    default: () => ({ message: 'hello' })
  },
  // Custom validator
  propF: {
    validator(value: string) {
      return ['success', 'warning', 'danger'].includes(value)
    }
  }
})
</script>

Prop Types

Supported type values:

  • String, Number, Boolean, Array, Object
  • Date, Function, Symbol, Error
  • Custom classes (uses instanceof)
class Person {
  constructor(public name: string) {}
}

defineProps({
  author: Person // instanceof check
})

Nullable Props

defineProps({
  id: {
    type: [String, null],
    required: true
  }
})

Boolean Casting

Boolean props have special casting rules:

<script setup lang="ts">
defineProps({
  disabled: Boolean
})
</script>

<!-- equivalent to :disabled="true" -->
<MyComponent disabled />

<!-- equivalent to :disabled="false" -->
<MyComponent />

One-Way Data Flow

Props form a one-way binding: parent → child. Never mutate props directly.

const props = defineProps(['initialCounter'])

// ❌ Don't mutate props
props.initialCounter = 5

// ✅ Use local state initialized from prop
const counter = ref(props.initialCounter)

// ✅ Or use computed for transformations
const normalizedSize = computed(() => props.size.trim().toLowerCase())

Passing Props

<!-- Static -->
<BlogPost title="My Post" />

<!-- Dynamic -->
<BlogPost :title="post.title" />

<!-- Number (requires v-bind) -->
<BlogPost :likes="42" />

<!-- Boolean -->
<BlogPost is-published />
<BlogPost :is-published="false" />

<!-- Object spread -->
<BlogPost v-bind="post" />
<!-- equivalent to -->
<BlogPost :id="post.id" :title="post.title" />

Prop Name Casing

  • Declare with camelCase in JavaScript
  • Use kebab-case in templates
defineProps({
  greetingMessage: String
})
<MyComponent greeting-message="hello" />