Files
stack/packages/mosaic/framework/skills/vue-best-practices/reference/slot-named-scoped-explicit-default.md
T
fargo 1a822493ba format: apply repo prettier (3.8.1) to the folded skills tree
963 markdown files reformatted with the repository's pinned prettier so
pnpm format:check covers the folded tree like every other repo file.

The formatter's embedded-language pass also normalized code fences
(TS semicolons, closed HTML tags in examples, lowercased CSS hex colors,
one renumbered list that skipped an index). Alphanumeric token deltas vs
the fold commit were audited file-by-file; all are formatter-equivalent
markup normalizations plus the four sanitized skills.
2026-08-19 14:37:17 -05:00

3.1 KiB

title, impact, impactDescription, type, tags
title impact impactDescription type tags
Use Explicit Default Template When Mixing Named and Scoped Slots HIGH Mixing v-slot on component with named slots inside causes ambiguous scope and compilation errors gotcha
vue3
slots
scoped-slots
named-slots
compilation-error

Use Explicit Default Template When Mixing Named and Scoped Slots

Impact: HIGH - When a component uses both the default scoped slot and named slots, you must use an explicit <template #default> for the default slot. Using v-slot directly on the component while having nested named slot templates causes scope ambiguity and compilation errors.

Task Checklist

  • When using named slots alongside a default slot with props, always use explicit <template #default>
  • Never mix v-slot on the component element with <template #name> inside
  • Keep slot scope clear and unambiguous

Incorrect:

<script setup>
import MyComponent from './MyComponent.vue';
</script>

<template>
  <!-- BAD: v-slot on component + named template inside causes ambiguity -->
  <MyComponent v-slot="{ message }">
    <p>{{ message }}</p>

    <template #footer>
      <!-- Ambiguous: Is 'message' available here? Vue can't determine -->
      <p>Footer: {{ message }}</p>
    </template>
  </MyComponent>
</template>

This causes a compilation error because Vue cannot determine:

  1. Whether message from the default slot should be available in the footer slot
  2. Which scope applies to the non-template content

Correct:

<script setup>
import MyComponent from './MyComponent.vue';
</script>

<template>
  <!-- GOOD: Explicit template for each slot with clear scope -->
  <MyComponent>
    <template #default="{ message }">
      <p>{{ message }}</p>
    </template>

    <template #footer>
      <!-- Clear: footer slot has its own scope, no access to default's 'message' -->
      <p>Footer content here</p>
    </template>
  </MyComponent>
</template>

Correct - When Footer Also Has Props:

<script setup>
import MyComponent from './MyComponent.vue';
</script>

<template>
  <MyComponent>
    <template #default="{ message }">
      <p>{{ message }}</p>
    </template>

    <template #footer="{ year }">
      <!-- Each slot receives its own props -->
      <p>Copyright {{ year }}</p>
    </template>
  </MyComponent>
</template>

The Rule

When you have any named slots (<template #name>), always use explicit templates for all slots, including the default slot. This makes scope boundaries clear and prevents compilation errors.

Pattern Valid? Notes
v-slot on component only Yes Single default scoped slot
Named templates only Yes Multiple named slots
v-slot on component + named templates No Ambiguous scope
All explicit templates Yes Clear scope for each slot

Reference