All skills
onmax avatar

/vue

@de09c7b official
by Maxonmax/nuxt-skills715 stars
38

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/onmax/nuxt-skills/vue

This session only. Nothing lands on disk.

referencescore-new-apis.md

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

Reactivity, Lifecycle & Composables

Reactivity

ref vs shallowRef

import { ref, shallowRef } from 'vue'

// ref - deep reactivity (tracks nested changes)
const user = ref({ name: 'John', profile: { age: 30 } })
user.value.profile.age = 31  // Triggers reactivity

// shallowRef - only .value assignment triggers reactivity (better performance)
const data = shallowRef({ items: [] })
data.value.items.push('new')  // Does NOT trigger reactivity
data.value = { items: ['new'] }  // Triggers reactivity

Prefer shallowRef for large data structures or when deep reactivity is unnecessary.

computed

import { ref, computed } from 'vue'

const count = ref(0)

// Read-only computed
const doubled = computed(() => count.value * 2)

// Writable computed
const plusOne = computed({
  get: () => count.value + 1,
  set: (val) => { count.value = val - 1 }
})

reactive & readonly

import { reactive, readonly } from 'vue'

const state = reactive({ count: 0, nested: { value: 1 } })
state.count++  // Reactive

const readonlyState = readonly(state)
readonlyState.count++  // Warning, mutation blocked

Note: reactive() loses reactivity on destructuring. Use ref() or toRefs().

Watchers

watch

import { ref, watch } from 'vue'

const count = ref(0)

// Watch single ref
watch(count, (newVal, oldVal) => {
  console.log(`Changed from ${oldVal} to ${newVal}`)
})

// Watch getter
watch(
  () => props.id,
  (id) => fetchData(id),
  { immediate: true }
)

// Watch multiple sources
watch([firstName, lastName], ([first, last]) => {
  fullName.value = `${first} ${last}`
})

// Deep watch with depth limit (Vue 3.5+)
watch(state, callback, { deep: 2 })

// Once (Vue 3.4+)
watch(source, callback, { once: true })

watchEffect

Runs immediately and auto-tracks dependencies.

import { ref, watchEffect, onWatcherCleanup } from 'vue'

const id = ref(1)

watchEffect(async () => {
  const controller = new AbortController()

  // Cleanup on re-run or unmount (Vue 3.5+)
  onWatcherCleanup(() => controller.abort())

  const res = await fetch(`/api/${id.value}`, { signal: controller.signal })
  data.value = await res.json()
})

// Pause/resume (Vue 3.5+)
const { pause, resume, stop } = watchEffect(() => {})
pause()
resume()
stop()

Flush Timing

// 'pre' (default) - before component update
// 'post' - after component update (access updated DOM)
// 'sync' - immediate, use with caution

watch(source, callback, { flush: 'post' })
watchPostEffect(() => {})  // Alias for flush: 'post'

Lifecycle Hooks

import {
  onBeforeMount,
  onMounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted,
  onErrorCaptured,
  onActivated,      // KeepAlive
  onDeactivated,    // KeepAlive
  onServerPrefetch  // SSR only
} from 'vue'

onMounted(() => {
  console.log('DOM is ready')
})

onUnmounted(() => {
  // Cleanup timers, listeners, etc.
})

// Error boundary
onErrorCaptured((err, instance, info) => {
  console.error(err)
  return false  // Stop propagation
})

Effect Scope

Group reactive effects for batch disposal.

import { effectScope, onScopeDispose } from 'vue'

const scope = effectScope()

scope.run(() => {
  const count = ref(0)
  const doubled = computed(() => count.value * 2)

  watch(count, () => console.log(count.value))

  // Cleanup when scope stops
  onScopeDispose(() => {
    console.log('Scope disposed')
  })
})

// Dispose all effects
scope.stop()

Composables

Composables are functions that encapsulate stateful logic using Composition API.

Naming Convention

  • Start with use: useMouse, useFetch, useCounter

Pattern

// composables/useMouse.ts
import { ref, onMounted, onUnmounted } from 'vue'

export function useMouse() {
  const x = ref(0)
  const y = ref(0)

  const update = (e: MouseEvent) => {
    x.value = e.pageX
    y.value = e.pageY
  }

  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  return { x, y }
}

Accept Reactive Input

Use toValue() (Vue 3.3+) to normalize refs, getters, or plain values.

import { ref, watchEffect, toValue, type MaybeRefOrGetter } from 'vue'

export function useFetch(url: MaybeRefOrGetter<string>) {
  const data = ref(null)
  const error = ref(null)

  watchEffect(async () => {
    data.value = null
    error.value = null

    try {
      const res = await fetch(toValue(url))
      data.value = await res.json()
    } catch (e) {
      error.value = e
    }
  })

  return { data, error }
}

// Usage - all work:
useFetch('/api/users')
useFetch(urlRef)
useFetch(() => `/api/users/${props.id}`)

Return Refs (Not Reactive)

Always return plain object with refs for destructuring compatibility.

// Good - preserves reactivity when destructured
return { x, y }

// Bad - loses reactivity when destructured
return reactive({ x, y })
<!-- Source references: - https://vuejs.org/api/reactivity-core.html - https://vuejs.org/api/reactivity-advanced.html - https://vuejs.org/api/composition-api-lifecycle.html - https://vuejs.org/guide/reusability/composables.html -->

Source: SKILL.md on GitHub

No alerts9d5 checks · Risk SAFE
  • Gen Agent Trust Hub9d

    This skill provides a high-quality reference and set of code templates for Vue 3.5 development using the Composition API, sourced from official documentation and reputable community resources.

  • Socket9d

    No alerts

  • Snyk9d

    Risk: LOW · No issues

  • Runlayer7mo

    11 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

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

Last checked against GitHub 2 days ago.

Activeupdated last week
Other metadata
metadata
{
  "author": "Anthony Fu",
  "version": "2026.1.31",
  "source": "Generated from https://github.com/vuejs/docs, scripts at https://github.com/antfu/skills"
}

README badge

README badge for onmax/nuxt-skills/vue

Provides Composition API patterns, component architecture, testing practices, and TypeScript guidance for Vue 3 development. Covers .vue files, composables, reactivity, routing, and testing with Vitest and @vue/test-utils, organized as modular reference files loaded on-demand.

Generated from the current SKILL.md.

Does this skill cover Nuxt-specific patterns like server routes and file-based routing?
No. This skill focuses on Vue 3 components, composables, and client-side code. Load the separate `nuxt` skill for server routes, API endpoints, and file-based routing.
What testing framework does this skill assume?
Vitest with @vue/test-utils for component and composable testing, as documented in the testing reference.
Does this cover VueUse composables?
This skill references VueUse integration patterns in composables, but the dedicated `vueuse` skill is recommended for in-depth VueUse guidance.
Can I use this skill with Vue 2?
No. This skill targets Vue 3.5+ with Composition API patterns and modern reactivity features.
Should I load all the reference files at once?
No. Load only the reference files relevant to your current task to minimize context usage, such as references/components.md for .vue files or references/testing.md for test files.

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