Slots are how a parent component passes template content into designated areas of a child component. The child simply renders slot, and any content placed between the child's opening and closing tags is rendered there. When a component needs multiple insertion points, named slots allow the parent to target specific outlets using slot name="header" in the child and template #header in the parent. The # symbol is shorthand for v-slot:, and any unnamed content falls into the default slot. Scoped slots go further by letting the child pass data back to the parent's slot content, enabling the parent to customize rendering while the child owns the underlying data and iteration logic.
When data needs to flow through many layers of components, props become cumbersome—a problem often called prop drilling. Vue's provide and inject APIs solve this by allowing an ancestor to provide a value that any descendant can inject, regardless of how deeply nested it is. In the Composition API, the ancestor calls provide('theme', ref('dark')) and any descendant calls const theme = inject('theme'). Reactive values remain reactive through this channel because the ref itself is what is shared. Provide and inject are best reserved for app-wide concerns like theme, locale, or authentication, while complex shared state is generally better managed by Pinia.
Vue 3 also includes several built-in components and helpers that address more specialized needs. The Teleport component renders its content in a different DOM location than where it is logically placed, which is invaluable for modals, tooltips, and notifications that need to escape parent CSS constraints such as overflow: hidden. The Suspense component coordinates async dependencies by rendering a fallback slot while waiting for async components or an async setup() to resolve. Async components themselves, created with defineAsyncComponent, load their code on demand and integrate with route-based code splitting. Custom directives, defined as objects with lifecycle hooks like mounted, give low-level access to the DOM for reusable behavior such as auto-focus. Finally, helpers like toRefs() preserve reactivity when destructuring a reactive object, and shallowRef() creates a ref that is only reactive at the top level—useful as a performance optimization when the inner structure is large or managed externally.