Index of every page on this site: llms.txt
All skills
antfu avatar

/vue

@7de210b official
by Anthony Fuantfu/skills6k stars
342
Run it yourself

Vue 3 Composition API, script setup macros, reactivity system, and built-in components. Use when writing Vue SFCs, defineProps/defineEmits/defineModel, watchers, or using Transition/Teleport/Suspense/KeepAlive.

Use this Skill: https://skilld.dev/gh/antfu/skills/vue

Nothing lands on disk. Nothing to clean up.

Fork this Skill

Edit a local copy. It keeps the author and licence.

referencesadvanced-patterns.md

≈1.6k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Built-in Components & Directives

Transition

Animate enter/leave of a single element or component.

<template>
  <Transition name="fade">
    <div v-if="show">Content</div>
  </Transition>
</template>

<style>
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.3s ease;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
</style>

CSS Classes

Class When
{name}-enter-from Start state for enter
{name}-enter-active Active state for enter (add transitions here)
{name}-enter-to End state for enter
{name}-leave-from Start state for leave
{name}-leave-active Active state for leave
{name}-leave-to End state for leave

Transition Modes

<!-- Wait for leave to complete before enter -->
<Transition name="fade" mode="out-in">
  <component :is="currentView" />
</Transition>

JavaScript Hooks

<Transition
  @before-enter="onBeforeEnter"
  @enter="onEnter"
  @after-enter="onAfterEnter"
  @leave="onLeave"
  :css="false"
>
  <div v-if="show">Content</div>
</Transition>

<script setup lang="ts">
function onEnter(el: Element, done: () => void) {
  // Animate with JS library
  gsap.to(el, { opacity: 1, onComplete: done })
}
</script>

Appear on Initial Render

<Transition appear name="fade">
  <div>Shows with animation on mount</div>
</Transition>

TransitionGroup

Animate list items. Each child must have a unique key.

<template>
  <TransitionGroup name="list" tag="ul">
    <li v-for="item in items" :key="item.id">
      {{ item.text }}
    </li>
  </TransitionGroup>
</template>

<style>
.list-enter-active, .list-leave-active {
  transition: all 0.3s ease;
}
.list-enter-from, .list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}
/* Move animation for reordering */
.list-move {
  transition: transform 0.3s ease;
}
</style>

Teleport

Render content to a different DOM location.

<template>
  <button @click="open = true">Open Modal</button>
  
  <Teleport to="body">
    <div v-if="open" class="modal">
      Modal content rendered at body
    </div>
  </Teleport>
</template>

Props

<!-- CSS selector -->
<Teleport to="#modal-container">

<!-- DOM element -->
<Teleport :to="targetElement">

<!-- Disable teleport conditionally -->
<Teleport to="body" :disabled="isMobile">

<!-- Defer until target exists (Vue 3.5+) -->
<Teleport defer to="#late-rendered-target">

Suspense

Handle async dependencies with loading states. Experimental feature.

<template>
  <Suspense>
    <template #default>
      <AsyncComponent />
    </template>
    <template #fallback>
      <div>Loading...</div>
    </template>
  </Suspense>
</template>

Async Dependencies

Suspense waits for:

  • Components with async setup()
  • Components using top-level await in <script setup>
  • Async components created with defineAsyncComponent
<!-- AsyncComponent.vue -->
<script setup lang="ts">
const data = await fetch('/api/data').then(r => r.json())
</script>

Events

<Suspense
  @pending="onPending"
  @resolve="onResolve"
  @fallback="onFallback"
>
  ...
</Suspense>

KeepAlive

Cache component instances when toggled.

<template>
  <KeepAlive>
    <component :is="currentTab" />
  </KeepAlive>
</template>

Include/Exclude

<!-- By name (string or regex) -->
<KeepAlive include="ComponentA,ComponentB">
<KeepAlive :include="/^Tab/">
<KeepAlive :include="['TabA', 'TabB']">

<!-- Exclude -->
<KeepAlive exclude="ModalComponent">

<!-- Max cached instances -->
<KeepAlive :max="10">

Lifecycle Hooks

import { onActivated, onDeactivated } from 'vue'

onActivated(() => {
  // Called when component is inserted from cache
  fetchLatestData()
})

onDeactivated(() => {
  // Called when component is removed to cache
  pauseTimers()
})

v-memo

Skip re-renders when dependencies unchanged. Use for performance optimization.

<template>
  <div v-for="item in list" :key="item.id" v-memo="[item.selected]">
    <!-- Only re-renders when item.selected changes -->
    <ExpensiveComponent :item="item" />
  </div>
</template>

Equivalent to v-once when empty:

<div v-memo="[]">Never updates</div>

v-once

Render once, skip all future updates.

<span v-once>Static: {{ neverChanges }}</span>

Custom Directives

Create reusable DOM manipulations.

// Directive definition
const vFocus: Directive<HTMLElement> = {
  mounted: (el) => el.focus()
}

// Full hooks
const vColor: Directive<HTMLElement, string> = {
  created(el, binding, vnode, prevVnode) {},
  beforeMount(el, binding) {},
  mounted(el, binding) {
    el.style.color = binding.value
  },
  beforeUpdate(el, binding) {},
  updated(el, binding) {
    el.style.color = binding.value
  },
  beforeUnmount(el, binding) {},
  unmounted(el, binding) {}
}

Directive Arguments & Modifiers

<div v-color:background.bold="'red'">

<script setup lang="ts">
const vColor: Directive<HTMLElement, string> = {
  mounted(el, binding) {
    // binding.arg = 'background'
    // binding.modifiers = { bold: true }
    // binding.value = 'red'
    el.style[binding.arg || 'color'] = binding.value
    if (binding.modifiers.bold) {
      el.style.fontWeight = 'bold'
    }
  }
}
</script>

Global Registration

// main.ts
app.directive('focus', {
  mounted: (el) => el.focus()
})

Type global directives by extending the GlobalDirectives interface (not ComponentCustomProperties):

import type { Directive } from 'vue'

declare module 'vue' {
  interface GlobalDirectives {
    vFocus: Directive<HTMLElement>
  }
}
<!-- Source references: - https://vuejs.org/api/built-in-components.html - https://vuejs.org/guide/built-ins/transition.html - https://vuejs.org/guide/built-ins/teleport.html - https://vuejs.org/guide/built-ins/suspense.html - https://vuejs.org/guide/built-ins/keep-alive.html - https://vuejs.org/api/built-in-directives.html - https://vuejs.org/guide/reusability/custom-directives.html -->

Source: SKILL.md on GitHub

No rule matched.

skilld matched fixed text patterns in SKILL.md and file names. Patterns miss obfuscated code.

skilld run checks every file with the same patterns. It asks for approval before it loads a Skill with a behavior marked Needs approval.

No alerts1mo5 checks · Risk SAFE
  • Gen Agent Trust Hub1mo

    The skill provides comprehensive guidelines and references for Vue 3 Composition API and <script setup>. It contains standard code examples and documentation from reputable sources. No security risks were identified.

  • Socket1mo

    No alerts

  • Snyk1mo

    Risk: LOW · No issues

  • Runlayer8mo

    1/5 files flagged

  • ZeroLeaks6mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 7de210b. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last week.

Activeupdated last month
Other metadata
metadata
{
  "author": "Anthony Fu",
  "version": "2026.9.25",
  "source": "Generated from https://github.com/vuejs/docs, scripts at https://github.com/antfu/skills"
}
  • Vue
  • TypeScript
  • vue3
  • composition-api
  • script-setup
  • reactivity
  • components
  • sfc

README badge

README badge for antfu/skills/vue

Provides Vue 3 Composition API patterns, script setup macros (defineProps, defineEmits, defineModel), reactivity utilities (ref, computed, watch), and built-in components (Transition, Teleport, Suspense, KeepAlive). Use when writing Vue SFCs with TypeScript and <script setup> syntax.

Generated from the current SKILL.md.

Does this skill cover Vue 2 or Vue 3?
This skill is based on Vue 3.5 and uses the Composition API exclusively. It does not cover Vue 2 or the Options API.
Should I use script setup or the traditional script block?
Always use `<script setup lang="ts">`. The skill discourages the traditional `<script>` block in favor of the more concise setup macro syntax.
Does this skill cover advanced patterns like Transition and Suspense?
Yes. The skill includes Vue's built-in components (Transition, Teleport, Suspense, KeepAlive) and directives like v-memo and custom directives.
When should I use shallowRef instead of ref?
Use shallowRef when deep reactivity is not needed, as it offers better performance than ref for large objects or arrays.
Does this skill recommend TypeScript?
Yes. The skill prefers TypeScript over JavaScript and all examples use `lang="ts"`.

Generated from the current SKILL.md. These answers refresh after source changes.