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.

referenceperf-computed-object-stability.md

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

Return Stable Object References from Computed Properties

Impact: MEDIUM - In Vue 3.4+, computed properties only trigger effects when their value changes. However, if a computed returns a new object each time, Vue cannot detect that the values inside are the same. This causes unnecessary effect re-runs.

For primitive values, Vue 3.4+ handles this automatically. For objects, manually compare and return the previous value when nothing meaningful has changed.

Task Checklist

  • For computed properties returning primitives, Vue 3.4+ handles stability automatically
  • For computed properties returning objects, compare with previous value and return old reference if unchanged
  • Always perform the full computation before comparing (to track dependencies correctly)
  • Consider if you really need to return an object, or if primitives would suffice

Incorrect:

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

const count = ref(0)

// BAD: Returns new object every time, always triggers effects
const stats = computed(() => {
  return {
    isEven: count.value % 2 === 0,
    doubleValue: count.value * 2
  }
})

watchEffect(() => {
  console.log('Stats changed:', stats.value)
  // Logs on EVERY count change, even when isEven hasn't changed
  // count: 0 -> 2 -> 4: isEven is always true, but effect runs each time
})
</script>

Correct:

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

const count = ref(0)

// GOOD (Vue 3.4+): Primitive computed - automatic stability
const isEven = computed(() => count.value % 2 === 0)

watchEffect(() => {
  console.log('isEven:', isEven.value)
  // Only logs when isEven actually changes (0, 2, 4 won't re-trigger)
})

// GOOD (Vue 3.4+): Manual comparison for object returns
const stats = computed((oldValue) => {
  // Step 1: Always compute the new value first (to track dependencies)
  const newValue = {
    isEven: count.value % 2 === 0,
    category: count.value < 10 ? 'small' : 'large'
  }

  // Step 2: Compare with previous value
  if (oldValue &&
      oldValue.isEven === newValue.isEven &&
      oldValue.category === newValue.category) {
    return oldValue  // Return old reference - no effect triggers
  }

  return newValue
})

watchEffect(() => {
  console.log('Stats changed:', stats.value)
  // Now only logs when isEven or category actually changes
})
</script>

Primitive vs Object Computed Behavior (Vue 3.4+)

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

const count = ref(0)

// PRIMITIVE: Vue automatically detects value hasn't changed
const isEven = computed(() => count.value % 2 === 0)

watchEffect(() => console.log(isEven.value))  // true

count.value = 2  // isEven still true - NO log
count.value = 4  // isEven still true - NO log
count.value = 3  // isEven now false - logs: false

// OBJECT: New reference every time (without manual comparison)
const obj = computed(() => ({ isEven: count.value % 2 === 0 }))

watchEffect(() => console.log(obj.value))  // { isEven: true }

count.value = 2  // Logs again! New object reference
count.value = 4  // Logs again! New object reference

Advanced: Deep Object Comparison

import { ref, computed } from 'vue'
import { isEqual } from 'lodash-es'  // For deep comparison

const filters = ref({ category: 'all', sortBy: 'date', page: 1 })

// For complex objects, use deep comparison
const activeFilters = computed((oldValue) => {
  const newValue = {
    ...filters.value,
    hasFilters: filters.value.category !== 'all' || filters.value.sortBy !== 'date'
  }

  // Deep compare for complex objects
  if (oldValue && isEqual(oldValue, newValue)) {
    return oldValue
  }

  return newValue
})

Important: Always Compute Before Comparing

// BAD: Early return prevents dependency tracking
const optimized = computed((oldValue) => {
  if (oldValue && someCondition) {
    return oldValue  // Dependencies not tracked!
  }
  return computeExpensiveValue()
})

// GOOD: Compute first, then compare
const optimized = computed((oldValue) => {
  const newValue = computeExpensiveValue()  // Always track dependencies
  if (oldValue && newValue === oldValue) {
    return oldValue
  }
  return newValue
})

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.