All skills
vuejs-ai avatar

/vue-debug-guides

@a5fc891 official
by Vue AIvuejs-ai/skills2.9k stars
167

Vue 3 debugging and error handling for runtime errors, warnings, async failures, and SSR/hydration issues. Use when diagnosing or fixing Vue issues.

Use this Skill: https://skilld.dev/gh/vuejs-ai/skills/vue-debug-guides

This session only. Nothing lands on disk.

referencesfc-script-setup-reactivity.md

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

Variables in Script Setup Are Not Reactive by Default

Impact: HIGH - Unlike Options API's data() which automatically makes properties reactive, variables declared in <script setup> are plain JavaScript values. You must explicitly use ref() or reactive() to make them reactive. Forgetting this causes the UI to not update when values change.

Task Checklist

  • Always wrap primitive values (strings, numbers, booleans) with ref()
  • Use reactive() for objects when you don't need to reassign the whole object
  • Remember to access .value on refs in script (not needed in templates)
  • Use computed() from Vue, not a plain function, for derived reactive state

Problematic Code:

<script setup>
// BAD: These are NOT reactive!
let count = 0
let message = 'Hello'
let user = { name: 'John', age: 30 }

function increment() {
  count++  // This change won't update the UI!
}

function updateMessage() {
  message = 'World'  // UI won't reflect this change!
}
</script>

<template>
  <div>
    <!-- Will always show initial values -->
    <p>Count: {{ count }}</p>
    <p>Message: {{ message }}</p>
    <button @click="increment">Increment</button>
    <button @click="updateMessage">Update</button>
  </div>
</template>

Correct Code:

<script setup>
import { ref, reactive, computed } from 'vue'

// GOOD: Primitives wrapped with ref()
const count = ref(0)
const message = ref('Hello')

// GOOD: Object with reactive()
const user = reactive({ name: 'John', age: 30 })

// GOOD: Computed for derived state
const doubleCount = computed(() => count.value * 2)

function increment() {
  count.value++  // Use .value for refs in script
}

function updateMessage() {
  message.value = 'World'
}

function updateUser() {
  user.name = 'Jane'  // No .value needed for reactive objects
}
</script>

<template>
  <div>
    <!-- No .value needed in templates - Vue unwraps automatically -->
    <p>Count: {{ count }}</p>
    <p>Double: {{ doubleCount }}</p>
    <p>Message: {{ message }}</p>
    <p>User: {{ user.name }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

Common Mistake: Plain Computed

<script setup>
import { ref } from 'vue'

const items = ref([1, 2, 3, 4, 5])

// BAD: Plain function, not reactive - won't update when items change
const total = items.value.reduce((sum, n) => sum + n, 0)

// BAD: Arrow function - recalculates but Vue doesn't track it
const getTotal = () => items.value.reduce((sum, n) => sum + n, 0)
</script>

<template>
  <!-- total never updates, getTotal works but isn't optimal -->
  <p>Total: {{ total }}</p>
</template>
<script setup>
import { ref, computed } from 'vue'

const items = ref([1, 2, 3, 4, 5])

// GOOD: computed() tracks dependencies and caches result
const total = computed(() => items.value.reduce((sum, n) => sum + n, 0))
</script>

<template>
  <p>Total: {{ total }}</p>  <!-- Updates when items change -->
</template>

When to Use ref() vs reactive()

<script setup>
import { ref, reactive } from 'vue'

// Use ref() for:
// - Primitives (string, number, boolean)
// - Values you might reassign entirely
const count = ref(0)
const isLoading = ref(false)
const selectedId = ref<number | null>(null)

// Use reactive() for:
// - Objects/arrays you'll mutate but not reassign
// - When you want to avoid .value
const form = reactive({
  name: '',
  email: '',
  errors: []
})

// Gotcha: Can't reassign reactive objects
const user = reactive({ name: 'John' })
// user = { name: 'Jane' }  // This breaks reactivity!
// user.name = 'Jane'       // This works

// Use ref() if you need to reassign objects
const userData = ref({ name: 'John' })
userData.value = { name: 'Jane' }  // This works
</script>

Template Automatic Unwrapping

Vue automatically unwraps refs in templates:

<script setup>
import { ref } from 'vue'

const count = ref(0)
const user = ref({ name: 'John' })
</script>

<template>
  <!-- All of these work - no .value needed -->
  <p>{{ count }}</p>
  <p>{{ user.name }}</p>
  <input v-model="count" type="number">
  <button @click="count++">Increment</button>
</template>

But in event handlers written inline, you might still need .value:

<template>
  <!-- This works (Vue handles it) -->
  <button @click="count++">+1</button>

  <!-- For complex logic, .value may be needed -->
  <button @click="() => { count.value = Math.max(0, count.value - 1) }">
    -1 (min 0)
  </button>
</template>

Reference

Source: SKILL.md on GitHub

1 warning17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    This skill is a comprehensive collection of educational debugging guides and best practices for Vue 3 developers. It contains no executable code or malicious instructions and focuses solely on diagnosing common runtime errors and performance issues.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer7mo

    140/140 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

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

Last checked against GitHub 2 months ago.

Steadyupdated 8 months ago

README badge

README badge for vuejs-ai/skills/vue-debug-guides

Guides for diagnosing Vue 3 runtime errors, reactivity bugs, component lifecycle issues, and SSR hydration problems. Covers reactivity traps (refs, computed, watchers), component mechanics (props, emits, slots), templates (v-if, v-for, refs), forms (v-model), and composition API gotchas.

Generated from the current SKILL.md.

Does this cover Vue 2 or only Vue 3?
This skill is for Vue 3 only. It addresses Vue 3-specific debugging patterns like reactivity proxies, script setup, and defineEmits/defineProps.
Does this skill help with performance optimization?
No. This skill focuses on runtime errors, warnings, and behavioral bugs. For development best practices and optimization, use the separate `vue-best-practices` skill.
What kinds of issues does this cover?
Reactivity traps (refs, computed, watchers), component lifecycle bugs, template directives, form binding edge cases, SSR/hydration mismatches, slot scoping, and async-related failures.
Does this include debugging for Nuxt or other Vue frameworks?
No. This skill focuses on core Vue 3 runtime issues. Framework-specific bugs are outside its scope.

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