Refactor high-complexity React components in Dify frontend. Use when `pnpm analyze-component...
npx skills add ngxtm/devkit --skill "vue-expert"
Install specific skill from multi-skill repository
# Description
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.
# SKILL.md
name: vue-expert
description: 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.
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
- Identify the Vue-specific issue category
- Check for common anti-patterns in that category
- Apply progressive fixes (minimal → better → complete)
- 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:
- https://vuejs.org/guide/essentials/reactivity-fundamentals.html
- https://vuejs.org/api/composition-api-setup.html
- https://vuejs.org/guide/reusability/composables.html
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:
- https://vuejs.org/guide/essentials/reactivity-fundamentals.html
- https://vuejs.org/guide/essentials/watchers.html
- https://vuejs.org/guide/essentials/computed.html
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:
- https://vuejs.org/api/composition-api-lifecycle.html
- https://vuejs.org/guide/components/lifecycle.html
- https://vuejs.org/guide/built-ins/suspense.html
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:
- https://pinia.vuejs.org/core-concepts/
- https://pinia.vuejs.org/core-concepts/state.html
- https://pinia.vuejs.org/core-concepts/actions.html
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:
- https://vuejs.org/guide/components/props.html
- https://vuejs.org/guide/components/events.html
- https://vuejs.org/guide/components/provide-inject.html
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:
- https://nuxt.com/docs/guide/concepts/rendering
- https://nuxt.com/docs/api/components/client-only
- https://nuxt.com/docs/api/composables/use-async-data
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:
- https://vuejs.org/guide/essentials/list.html
- https://vuejs.org/guide/essentials/template-refs.html
- https://vuejs.org/guide/best-practices/performance.html
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
.valuein script, auto-unwrapped in template - [ ]
reactive()not destructured directly (usetoRefs()) - [ ]
computed()used for derived state - [ ] Composables properly extracted for reusable logic
- [ ] Proper TypeScript typing with
defineProps<>()anddefineEmits<>()
Reactivity Patterns
- [ ] Appropriate use of
refvsreactive - [ ]
shallowRef/shallowReactivefor large objects - [ ]
watchhas proper source and options - [ ]
watchEffectcleanup handled correctly - [ ] No computed properties with side effects
- [ ]
toRefused 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
- Reactive Overuse: Don't make everything reactive - use regular variables for static data
- Watcher Chains: Avoid complex watcher dependencies - prefer computed properties
- Prop Drilling: Use provide/inject or Pinia for deeply nested data
- Mixin Usage: Mixins are legacy - use composables in Vue 3
- 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
# Supported AI Coding Agents
This skill is compatible with the SKILL.md standard and works with all major AI coding agents:
Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.