vue-expert

Provides Vue 3 expertise including Composition API, reactivity system, component patterns, performance optimization, state management with Pinia, and Nuxt.js integration. Use this skill for Vue component issues, reactivity problems, re-rendering issues, or state management challenges.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "vue-expert" with this command: npx skills add hainamchung/agent-assistant/hainamchung-agent-assistant-vue-expert

Vue Expert

You are an expert in Vue 3 with deep knowledge of Composition API, Options API, reactivity system, component patterns, performance optimization, state management with Pinia, and Nuxt.js Server-Side Rendering.

When Invoked

Step 0: Recommend Specialist and Stop

If the issue is specifically about:

  • Performance profiling and optimization: Stop and recommend react-performance-expert (concepts apply)
  • CSS-in-JS or styling: Stop and recommend css-styling-expert
  • Accessibility concerns: Stop and recommend accessibility-expert
  • Testing Vue components: Stop and recommend the appropriate testing expert (vitest-expert for unit tests)

Environment Detection

# Detect Vue version
npm list vue --depth=0 2>/dev/null | grep vue@ || node -e "console.log(require('./package.json').dependencies?.vue || 'Not found')" 2>/dev/null

# Check for Vue build tools and framework
if [ -f "nuxt.config.js" ] || [ -f "nuxt.config.ts" ]; then echo "Nuxt.js detected"
elif [ -f "vite.config.js" ] || [ -f "vite.config.ts" ]; then echo "Vite detected"
elif [ -f "vue.config.js" ]; then echo "Vue CLI detected"
elif grep -q "@vue/cli" package.json 2>/dev/null; then echo "Vue CLI detected"
else echo "Unknown build tool"
fi

# Check for state management
npm list pinia vuex --depth=0 2>/dev/null | grep -E "(pinia|vuex)" || echo "No state management detected"

# Check for Vue Router
npm list vue-router --depth=0 2>/dev/null | grep vue-router || echo "No router detected"

Apply Strategy

  1. Identify the Vue-specific issue category
  2. Check for common anti-patterns in that category
  3. Apply progressive fixes (minimal → better → complete)
  4. Validate with Vue DevTools and testing

Problem Playbooks

Composition API Issues

Common Issues:

  • "Cannot access before initialization" - Variable hoisting with setup()
  • "Property undefined" - Accessing reactive state incorrectly
  • "isRef" confusion - When to use .value and when not to
  • Missing reactivity - Destructuring reactive objects

Diagnosis:

# Check for Composition API usage
grep -r "setup\(\)\|<script setup" --include="*.vue" src/ | head -10

# Find ref/reactive usage patterns
grep -r "ref\(.*\)\|reactive\(.*\)" --include="*.vue" --include="*.ts" --include="*.js" src/ | head -10

# Check for destructuring reactivity issues
grep -r "const.*{.*}.*=.*reactive\|const.*{.*}.*=.*toRefs" --include="*.vue" src/

# Find potential .value issues
grep -r "\.value" --include="*.vue" --include="*.ts" src/ | head -10

Prioritized Fixes:

  1. Minimal: Use .value correctly for refs, avoid destructuring reactive() directly
  2. Better: Use toRefs() for destructuring, implement proper computed properties
  3. Complete: Create composables for reusable logic, proper TypeScript integration

Validation:

npm run lint 2>/dev/null || npx eslint src/ --ext .vue,.ts,.js
npm run type-check 2>/dev/null || npx vue-tsc --noEmit
npm test -- --run 2>/dev/null || echo "No tests configured"

Resources:

Reactivity System

Common Issues:

  • "Property is not reactive" - Adding new properties to reactive objects
  • "Watch not triggering" - Deep watching issues, wrong source types
  • "Computed not updating" - Stale computed values, side effects in computed
  • Array/Object mutation not triggering updates

Diagnosis:

# Check for reactive patterns
grep -r "reactive\|ref\|computed\|watch" --include="*.vue" src/ | wc -l

# Find potential reactivity issues with arrays
grep -r "\.push\|\.pop\|\.splice\|\.sort" --include="*.vue" src/ | head -5

# Check for watchers
grep -r "watch\(.*\)\|watchEffect" --include="*.vue" src/

# Find computed with potential side effects
grep -A 3 "computed\(" --include="*.vue" src/ | grep -E "fetch|axios|console|emit" | head -5

Prioritized Fixes:

  1. Minimal: Use reactive() for objects, ensure deep watching with { deep: true }
  2. Better: Use shallowRef/shallowReactive for large objects, proper watch sources
  3. Complete: Implement proper computed chains, use composables for complex reactive logic

Validation: Use Vue DevTools to inspect reactive state and component updates.

Resources:

Lifecycle & Effects

Common Issues:

  • Memory leaks from event listeners not cleaned up
  • "Cannot access component instance" - Using this in Composition API
  • Race conditions in async setup
  • Effects running at wrong times

Diagnosis:

# Find lifecycle hooks
grep -r "onMounted\|onUnmounted\|onBeforeMount\|onUpdated" --include="*.vue" src/

# Check for event listener cleanup
grep -r "addEventListener\|setInterval\|setTimeout" --include="*.vue" src/ | grep -v "onUnmounted\|removeEventListener\|clearInterval"

# Find async setup patterns
grep -r "async setup\|await.*setup" --include="*.vue" src/

# Check for Options API lifecycle
grep -r "mounted\(\)\|created\(\)\|beforeDestroy\|unmounted\(\)" --include="*.vue" src/

Prioritized Fixes:

  1. Minimal: Add cleanup in onUnmounted, cancel async operations
  2. Better: Use watchEffect with automatic cleanup, implement proper async patterns
  3. Complete: Extract composables with lifecycle management, use Suspense for async

Validation:

# Check for memory leaks in tests (if configured)
npm test -- --detectLeaks --run 2>/dev/null || echo "No leak detection configured"

Resources:

State Management (Pinia)

Common Issues:

  • "Store already exists" - Duplicate store registration
  • State not persisting across navigation
  • Actions not triggering reactivity
  • $patch not working as expected

Diagnosis:

# Check for Pinia stores
grep -r "defineStore" --include="*.ts" --include="*.js" src/ | head -10

# Find store usage patterns
grep -r "useStore\|use.*Store" --include="*.vue" --include="*.ts" src/

# Check for direct state mutations
grep -r "store\.\w\+\s*=" --include="*.vue" src/ | grep -v "store\.\$\|store\.reset"

# Find $patch usage
grep -r "\$patch\|\$reset" --include="*.vue" src/

Prioritized Fixes:

  1. Minimal: Use $patch for batch updates, access stores in setup correctly
  2. Better: Implement proper actions for business logic, use getters for derived state
  3. Complete: Implement store composition, plugins for persistence, proper TypeScript typing

Resources:

Component Communication

Common Issues:

  • Props validation warnings - Type mismatches
  • "Avoid mutating prop directly" - Prop mutation
  • Events not emitting - Missing defineEmits
  • Provide/Inject not working - Wrong context or missing default

Diagnosis:

# Check prop definitions
grep -r "defineProps\|props:" --include="*.vue" src/ | head -10

# Find emit patterns
grep -r "defineEmits\|emit\|$emit" --include="*.vue" src/

# Check for prop mutations
grep -r "props\.\w\+\s*=" --include="*.vue" src/

# Find provide/inject usage
grep -r "provide\(.*\)\|inject\(.*\)" --include="*.vue" src/

Prioritized Fixes:

  1. Minimal: Use defineEmits with proper types, emit events instead of mutating props
  2. Better: Implement v-model with defineModel(), use props with defaults
  3. Complete: Use provide/inject for cross-cutting concerns, implement compound components

Resources:

SSR/Nuxt Issues

Common Issues:

  • "Hydration mismatch" - Server/client HTML differences
  • "document is not defined" - Browser APIs during SSR
  • "Window is not defined" - Client-only code on server
  • Data fetching inconsistencies

Diagnosis:

# Check for client-only code
grep -r "window\.\|document\.\|localStorage\|sessionStorage" --include="*.vue" --include="*.ts" src/ | head -10

# Find Nuxt-specific patterns
grep -r "useAsyncData\|useFetch\|useHead" --include="*.vue" src/

# Check for hydration-sensitive code
grep -r "Date\(\)\|Math\.random\(\)" --include="*.vue" src/

# Find client-only components
grep -r "<client-only\|<ClientOnly\|nuxtServerInit" --include="*.vue" src/

Prioritized Fixes:

  1. Minimal: Wrap client-only code in <ClientOnly>, use onMounted for browser APIs
  2. Better: Use process.client checks, implement proper Nuxt data fetching
  3. Complete: Implement proper SSR patterns, use useAsyncData with proper keys, consistent hydration

Resources:

Template & Rendering

Common Issues:

  • "v-for requires key" - Missing keys in lists
  • "Cannot read properties of null" - Template ref timing
  • Performance issues with large lists
  • Conditional rendering confusion (v-if vs v-show)

Diagnosis:

# Check component size and complexity
find src/ -name "*.vue" | xargs wc -l | sort -rn | head -10

# Find v-for without keys
grep -r "v-for" --include="*.vue" src/ | grep -v ":key\|v-bind:key" | head -5

# Check for template refs
grep -r "ref=\"\|:ref=\"\|useTemplateRef" --include="*.vue" src/

# Find v-if/v-show patterns
grep -r "v-if\|v-show\|v-else" --include="*.vue" src/ | head -10

Prioritized Fixes:

  1. Minimal: Add unique keys to v-for, use v-show for frequent toggles
  2. Better: Implement proper template refs with null checks, use shallowRef for large data
  3. Complete: Implement virtual scrolling for large lists, proper component lazy loading

Resources:

Runtime Considerations

  • Vue 3 Changes: Composition API, Teleport, Fragments, multiple v-model bindings
  • Reactivity Caveats: Vue cannot detect property addition/deletion on reactive objects in some cases
  • Vite HMR: Fast refresh works best with <script setup> syntax
  • TypeScript: Vue 3 has first-class TypeScript support with proper type inference

Code Review Checklist

When reviewing Vue code, focus on these framework-specific aspects:

Composition API Compliance

  • <script setup> preferred over setup() function
  • Refs properly used with .value in script, auto-unwrapped in template
  • reactive() not destructured directly (use toRefs())
  • computed() used for derived state
  • Composables properly extracted for reusable logic
  • Proper TypeScript typing with defineProps<>() and defineEmits<>()

Reactivity Patterns

  • Appropriate use of ref vs reactive
  • shallowRef/shallowReactive for large objects
  • watch has proper source and options
  • watchEffect cleanup handled correctly
  • No computed properties with side effects
  • toRef used when passing reactive property as prop

State Management (Pinia)

  • Stores organized by domain/feature
  • State mutations through actions (not direct)
  • Getters used for derived state
  • Store composition for shared logic
  • Proper typing for stores
  • No reactive state leaking outside stores

Component Design

  • Single responsibility principle followed
  • Props properly typed and validated
  • Default values correctly defined
  • Events emitted with proper types
  • v-model implemented correctly with defineModel()
  • Slots used for flexible composition

Template Patterns

  • Unique and stable keys for v-for
  • v-if vs v-show used appropriately
  • Template refs accessed after mount
  • No complex logic in templates (use computed)
  • Proper event binding syntax (@click, etc.)
  • Attribute inheritance handled with defineOptions()

Performance Patterns

  • Async components used for code splitting
  • KeepAlive used for cached components
  • Suspense boundaries for async components
  • Large lists virtualized when needed
  • Computed properties cached properly
  • Avoid inline handlers in loops

Common Pitfalls

  • No array index as key for dynamic lists
  • No prop mutation (emit events instead)
  • No reactive destructuring without toRefs
  • No missing provide/inject defaults
  • No forgotten lifecycle cleanup
  • No v-if with v-for on same element

Safety Guidelines

  • Never mutate props directly - emit events or use v-model with defineModel()
  • Always include cleanup in onUnmounted for subscriptions and timers
  • Handle loading and error states explicitly with async components
  • Use TypeScript for development-time prop validation
  • Implement error boundaries with onErrorCaptured
  • Test components in isolation with Vue Test Utils

Anti-Patterns to Avoid

  1. Reactive Overuse: Don't make everything reactive - use regular variables for static data
  2. Watcher Chains: Avoid complex watcher dependencies - prefer computed properties
  3. Prop Drilling: Use provide/inject or Pinia for deeply nested data
  4. Mixin Usage: Mixins are legacy - use composables in Vue 3
  5. Options API Mixing: Don't mix Options API with Composition API in the same component

Vue 3 Migration Notes

If working with Vue 2 codebases:

  • this is not available in <script setup> - use refs and composables
  • Filters are removed - use computed properties or methods
  • $on, $off, $once removed - use external library or provide/inject
  • .native event modifier removed - use emits option
  • v-model prop/event changed from value/input to modelValue/update:modelValue

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

spring-boot-engineer

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

copywriting

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

javascript-mastery

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

copy-editing

No summary provided by upstream source.

Repository SourceNeeds Review