DEV Community

Cover image for The Vue Slot Shorthand That Makes Templates Cleaner
Kevin Coto🚀💡
Kevin Coto🚀💡

Posted on • Edited on

The Vue Slot Shorthand That Makes Templates Cleaner

The # Syntax for Named Slots

Vue's template syntax has a shorthand for named slots that many developers overlook. It does not save many keystrokes, but it improves clarity when you are working with components that expose multiple slots.

The standard way to pass content to a named slot uses the v-slot directive.

<Todo>
  <template v-slot:description>
    <Item />
  </template>
</Todo>
Enter fullscreen mode Exit fullscreen mode

The shorthand replaces v-slot: with #.

<Todo>
  <template #description>
    <Item />
  </template>
</Todo>
Enter fullscreen mode Exit fullscreen mode

The difference is small on its own. It becomes more meaningful as the template grows.


Why It Matters

Components with multiple named slots benefit the most. Consider a layout component with slots for header, sidebar, main, and footer.

<Layout>
  <template v-slot:header>
    <HeaderContent />
  </template>
  <template v-slot:sidebar>
    <SideNav />
  </template>
  <template v-slot:main>
    <PageContent />
  </template>
  <template v-slot:footer>
    <FooterContent />
  </template>
</Layout>
Enter fullscreen mode Exit fullscreen mode

With the shorthand:

<Layout>
  <template #header>
    <HeaderContent />
  </template>
  <template #sidebar>
    <SideNav />
  </template>
  <template #main>
    <PageContent />
  </template>
  <template #footer>
    <FooterContent />
  </template>
</Layout>
Enter fullscreen mode Exit fullscreen mode

The difference is visual clarity. The # symbol reads as a marker for slots, similar to how @ marks events and : marks bindings in Vue templates. Consistency across these prefixes helps the eye parse the template structure faster.


Dynamic Slot Names

Vue also supports dynamic slot names using bracket notation.

<template #[dynamicSlotName]>
  <SomeContent />
</template>
Enter fullscreen mode Exit fullscreen mode

This works with both v-slot: and # syntax. It is useful when rendering slot content based on configuration or when building generic wrapper components.

<GenericWrapper>
  <template v-for="slotName in availableSlots" :key="slotName" #[slotName]>
    <DynamicContent :name="slotName" />
  </template>
</GenericWrapper>
Enter fullscreen mode Exit fullscreen mode

Scoped Slots with the Shorthand

Named slots often pass data back to the parent. The shorthand handles this as well.

<List :items="items">
  <template #item="{ item, index }">
    <div class="list-item">
      <span>{{ index }}.</span>
      <span>{{ item.label }}</span>
    </div>
  </template>
</List>
Enter fullscreen mode Exit fullscreen mode

The destructuring in the slot parameter follows the same pattern as JavaScript function parameters. You pull out only the values you need.


When the Default Slot is Enough

Not every component needs named slots. If a component only passes content through one slot, the default (unnamed) slot is simpler.

<Button @click="handleClick">
  Click me
</Button>
Enter fullscreen mode Exit fullscreen mode

Introducing named slots adds complexity. Use them when the component truly has multiple insertion points. Over engineering slot APIs makes components harder to use, not more flexible.


Summary

  • The # shorthand replaces v-slot: for cleaner templates.
  • Multiple named slots benefit the most from the shorthand.
  • Dynamic slot names work with both syntaxes.
  • Scoped slots pass data through the same shorthand.
  • Use default slots for simple components and named slots for components with multiple insertion points.

Small patterns like this compound across a codebase. A team that consistently uses the shorthand will find slot boundaries easier to spot during code reviews and debugging.

Top comments (0)