Skip to content

Chapter 6 of 8

Slots, Provide/Inject, and Advanced Features

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.

All chapters
  1. 1Introduction to Vue and the Reactivity System
  2. 2Component API Styles: Options vs Composition
  3. 3Template Directives
  4. 4Computed Properties and Watchers
  5. 5Component Lifecycle, Props, and Emits
  6. 6Slots, Provide/Inject, and Advanced Features
  7. 7State Management with Pinia
  8. 8Routing with Vue Router

Drill it

Reading is not remembering. These come from the Vue Framework deck:

Q

What is Vue.js?

Vue.js is a progressive JavaScript framework for building user interfaces. It is designed to be incrementally adoptable and focuses on the view layer, making it...

Q

What is the Vue reactivity system?

The Vue reactivity system automatically tracks dependencies and updates the DOM when reactive state changes. In Vue 3, it uses Proxy objects (instead of Object....

Q

How do you create a reactive object in Vue 3?

Use reactive() from the Composition API:import { reactive } from 'vue'const state = reactive({ count: 0, name: 'Vue' })This returns a deeply reactive proxy of t...

Q

What is the difference between ref() and reactive()?

ref() wraps a single value (primitive or object) and requires .value to access it in script. reactive() wraps an object and provides direct property access.cons...