Vue 3 Composition API: defineProps, defineEmits, defineExpose, defineOptions, and defineSlots – Detailed Guide and Usage Examples

This article provides a comprehensive overview of Vue 3's new composition API functions—defineProps, defineEmits, defineExpose, defineOptions, and defineSlots—explaining their purposes, basic usage, practical examples, and suitable scenarios, helping developers master component communication, reuse, and advanced configuration in modern frontend development.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Vue 3 Composition API: defineProps, defineEmits, defineExpose, defineOptions, and defineSlots – Detailed Guide and Usage Examples

Vue 3 introduces a set of composition‑API helper functions— defineProps, defineEmits, defineExpose, defineOptions, and defineSlots —that replace many of the traditional Options‑API patterns and enable more modular component development.

Function Overview

Function

Purpose

Basic Usage

Notes defineProps Declare component props const props = defineProps({ ... }) Provides type‑safe prop definitions and validation. defineEmits Declare events the component can emit const emit = defineEmits(["update:count"]) Replaces the traditional $emit with a type‑safe API. defineExpose Expose methods or properties to the parent defineExpose({ reset }) Useful for highly reusable components that need to expose internal logic. defineOptions Set component options (name, components, directives) inside

setup
defineOptions({ name: "MyComp", components: {...}, directives: {...} })

Bridges Options‑API configuration with the composition API. defineSlots Access named and default slots programmatically const slots = defineSlots() Simplifies dynamic slot handling for complex layouts.

Usage Example – defineProps

<!-- Counter.vue -->
<template>
  <div>
    <p>{{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const props = defineProps({
  initialCount: { type: Number, required: true }
})
const count = ref(props.initialCount)
function increment() { count.value++ }
</script>

Parent component that passes the prop:

<!-- Parent.vue -->
<template>
  <Counter :initialCount="100" />
</template>

<script setup lang="ts">
import Counter from './Counter.vue'
</script>

Usage Example – defineEmits

<!-- Counter.vue (with emits) -->
<script setup>
import { ref } from 'vue'
const props = defineProps({ initialCount: Number })
const emit = defineEmits(["update:count"])
const count = ref(props.initialCount)
function handleIncrement() {
  count.value++
  emit('update:count', count.value)
}
</script>

Parent listening to the emitted event:

<!-- Parent.vue -->
<template>
  <Counter :initialCount="100" @update:count="handleCountUpdate" />
</template>

<script setup lang="ts">
function handleCountUpdate(value: number) { console.log(value) }
</script>

Usage Example – defineExpose

<!-- Counter.vue exposing reset -->
<script setup>
import { ref, defineExpose } from 'vue'
const props = defineProps({ initialCount: Number })
const count = ref(props.initialCount)
function reset() { count.value = props.initialCount }
defineExpose({ reset })
</script>

Parent invoking the exposed method via ref:

<!-- Parent.vue -->
<template>
  <Counter ref="counter" :initialCount="10" />
  <button @click="counter.value.reset()">Reset Counter</button>
</template>

<script setup>
import { ref } from 'vue'
import Counter from './Counter.vue'
const counter = ref(null)
</script>

Usage Example – defineOptions

defineOptions({
  name: 'MyComponent',
  components: { ChildComponent },
  directives: { focus: { mounted(el) { el.focus() } } }
})

Usage Example – defineSlots

<!-- SlotComponent.vue -->
<template>
  <div class="header"><slot name="header" /></div>
  <div class="content"><slot /></div>
  <div class="footer"><slot name="footer" /></div>
</template>

<script setup>
import { defineSlots } from 'vue'
const slots = defineSlots()
console.log('Header:', slots.header ? slots.header() : 'No header')
console.log('Default:', slots.default ? slots.default() : 'No default')
console.log('Footer:', slots.footer ? slots.footer() : 'No footer')
</script>

Parent using the slots:

<!-- ParentComponent.vue -->
<template>
  <SlotComponent>
    <template #header><h2>Header Slot</h2></template>
    <template #footer><p>Footer Slot</p></template>
    Default content here
  </SlotComponent>
</template>

<script setup>
import SlotComponent from './SlotComponent.vue'
</script>

Applicable Scenarios Summary defineProps + defineEmits: Ideal for simple components and rapid development, providing basic prop and event handling. defineExpose: Suited for highly encapsulated components that need to expose internal methods. defineOptions: Best for complex components requiring extensive configuration (name, sub‑components, directives). defineSlots: Useful when dealing with dynamic content and advanced slot layouts.

Additional Tips

When using Vue 3 with ESLint, add the composition‑API helpers to the globals section of .eslintrc.js so the linter recognises them as read‑only globals.

// .eslintrc.js
module.exports = {
  env: { node: true, browser: true, es2021: true },
  parser: 'vue-eslint-parser',
  extends: ['eslint:recommended', 'plugin:vue/vue3-strongly-recommended'],
  parserOptions: { ecmaVersion: 12, parser: '@typescript-eslint/parser', sourceType: 'module' },
  plugins: ['vue', '@typescript-eslint'],
  rules: { /* …custom rules… */ },
  globals: {
    withDefaults: true,
    defineExpose: true,
    defineEmits: true,
    defineProps: true,
    defineOptions: true,
    defineSlots: true
  }
}

The withDefaults helper can be combined with defineProps to provide default values and improve TypeScript inference:

const props = withDefaults(defineProps({
  message: String,
  count: { type: Number, default: 0 }
}), { message: 'hello', count: 0 })

Conclusion

By mastering defineProps, defineEmits, defineExpose, defineOptions, and defineSlots, Vue 3 developers gain fine‑grained control over component interfaces, event flows, and configuration, leading to cleaner, more maintainable, and highly reusable frontend code.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Composition APIVue3defineProps
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.