Skip to content
Development
Skill

/web-framework-vue-composition-api

Vue 3 Composition API — reactivity primitives, composables, lifecycle, the 3.4+ and 3.5+ macros. Load when writing Vue 3 components or composables.

From plugin
agents-inc-skills
24200 skills
Install
$ npx -y skills add agents-inc/skills --skill web-framework-vue-composition-api --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/web-framework-vue-composition-api

Context preview

The summary Claude sees to decide when to auto-load this skill.

Vue 3 Composition API — reactivity primitives, composables, lifecycle, the 3.4+ and 3.5+ macros. Load when writing Vue 3 components or composables.

SKILL.md

web-framework-vue-composition-api.SKILL.md
name: web-framework-vue-composition-api
description: Vue 3 Composition API — reactivity primitives, composables, lifecycle, the 3.4+ and 3.5+ macros. Load when writing Vue 3 components or composables.

Vue 3 Composition API

> **Quick Guide:** `<script setup>` for every component. `ref()` for primitives and anything reassigned, `reactive()` for an object mutated in place. Reusable stateful logic goes into a `use*` composable that returns an object of refs. Everything opened in `onMounted` is closed in `onUnmounted`. The 3.4+ and 3.5+ macros — `defineModel()`, `useTemplateRef()`, `useId()`, `onWatcherCleanup()` — replace whole patterns that preceded them, and destructured props need a getter wrapper in `watch()`.

**Detailed Resources:**

  • [examples/core.md](examples/core.md) — a complete component, template refs, focus management
  • [examples/reactivity.md](examples/reactivity.md) — `ref`, `reactive`, `computed` and their anti-patterns
  • [examples/composables.md](examples/composables.md) — useFetch, useLocalStorage, useDebounce, useIntersectionObserver
  • [examples/lifecycle.md](examples/lifecycle.md) — WebSockets, timers, event listeners, cleanup
  • [examples/provide-inject.md](examples/provide-inject.md) — theme provider, typed injection keys
  • [examples/define-expose.md](examples/define-expose.md) — form field validation, parent-child coordination
  • [examples/vue-3-5-features.md](examples/vue-3-5-features.md) — defineModel, useTemplateRef, useId, onWatcherCleanup, reactive destructure, deferred Teleport
  • [examples/async.md](examples/async.md) — lazy loading, Suspense, async setup
  • [reference.md](reference.md) — decision trees, anti-patterns with corrected code, checklists, TypeScript patterns

---

Which path applies

  • **Vue on its own** — component data fetching goes through `watch`/`watchEffect` or an async composable, as Patterns 3 and 5 describe.
  • **Vue under a meta-framework** — the framework owns fetching, caching and SSR-safe hydration through its own composables; take Patterns 1, 2, 4 and 6–11 unchanged and let it handle the rest.

---

<critical_requirements>

Before writing Vue code

**Write components as `<script setup>`.** Bindings reach the template with no return statement, and the compiler macros — `defineProps`, `defineEmits`, `defineModel` — only exist inside it.

**Pair every `onMounted` setup with an `onUnmounted` teardown.** Timers, listeners, observers and sockets outlive the component otherwise, and nothing reports it.

**Pick `ref()` for primitives and anything you will reassign, `reactive()` for an object you mutate in place.** A reassigned `reactive` variable leaves the old proxy behind, still wired to the template.

**Prefix a composable with `use`.** The convention is what tells a reader — and the linter — that the function may call lifecycle hooks and must run during setup.

**Wrap a destructured prop in a getter for `watch()` — `watch(() => count, …)`.** Passing the value itself hands `watch` a number, which it can never see change.

</critical_requirements>

---

**Auto-detection:** Vue 3 Composition API, script setup, ref, reactive, computed, watch, watchEffect, composables, onMounted, onUnmounted, defineProps, defineEmits, defineExpose, defineModel, useTemplateRef, useId, onWatcherCleanup, provide, inject, InjectionKey, Suspense, toRefs, toValue, MaybeRefOrGetter

**Applies to:**

  • Reactive state with `ref`, `reactive`, `computed`, `watch` and `watchEffect`
  • Component contracts: props, emits, exposed methods, v-model
  • Composables for reusable stateful logic
  • Lifecycle and cleanup
  • Provide/inject, async components and Suspense

**Handled elsewhere:**

  • Styling — a `<style scoped>` block is Vue's, and which CSS approach fills it is not settled here
  • Application-wide state stores that outlive a component tree
  • Server-state caching, invalidation and request deduplication
  • Routing, and the data a route loads
  • Test doubles for the network

---

<philosophy>

Philosophy

The Composition API groups code by the concern it serves rather than by the kind of thing it is. One feature's state, its derived values, its watcher and its cleanup sit together and can be lifted out whole into a composable — where the Options API scattered the same feature across `data`, `computed`, `methods` and `mounted`, and offered no way to move it.

That is what makes a composable the unit of reuse: it is a plain function that happens to call reactive primitives, so it composes, takes arguments and returns whatever shape suits — no mixin merge order, no name collisions.

</philosophy>

---

<patterns>

Core patterns

Pattern 1: Script setup, props and emits

`defineProps` and `defineEmits` take type arguments, so the contract is declared once and checked at both ends.

<script setup lang="ts">
const props = defineProps<{
  userId: string;
  initialCount?: number;
}>();

const emit = defineEmits<{
  update: [value: number];
  submit: [];
}>();

const count = ref(props.initialCount ?? 0);
const doubleCount = computed(() => count.value * 2);
</script>

The named-tuple emit syntax (3.3+) documents each payload in the type itself.

Full code: [examples/core.md](examples/core.md)

---

Pattern 2: ref and reactive

const count = ref(0);
count.value++;

const state = reactive({
  user: null as User | null,
  settings: { theme: "light" },
});
state.settings.theme = "dark";

`.value` in script, unwrapped in template. Destructuring a `reactive` object copies its values out of the proxy — `toRefs(state)` is what keeps them connected.

Full code: [examples/reactivity.md](examples/reactivity.md)

---

Pattern 3: watch and watchEffect

`watch` names its source and gives you the previous value; `watchEffect` tracks whatever it reads and runs immediately. `onWatcherCleanup()` (3.5+) cancels work the next run supersedes.

watch(searchQuery, async (newQuery, oldQuery) => {
  /* … */
});

watchEffect(async () => {
  i
Read more
Ships withagents-inc-skills

The official skills marketplace for Agents Inc. 150+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?

Get the whole plugin

Other skills on agents-inc-skills.