@pythoughts/vue-skills-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/README.md +63 -0
  2. package/index.mjs +139 -0
  3. package/package.json +34 -0
  4. package/skills/create-adaptable-composable/SKILL.md +76 -0
  5. package/skills/vue-best-practices/SKILL.md +154 -0
  6. package/skills/vue-best-practices/references/animation-class-based-technique.md +254 -0
  7. package/skills/vue-best-practices/references/animation-state-driven-technique.md +291 -0
  8. package/skills/vue-best-practices/references/component-async.md +97 -0
  9. package/skills/vue-best-practices/references/component-data-flow.md +350 -0
  10. package/skills/vue-best-practices/references/component-fallthrough-attrs.md +174 -0
  11. package/skills/vue-best-practices/references/component-keep-alive.md +137 -0
  12. package/skills/vue-best-practices/references/component-slots.md +216 -0
  13. package/skills/vue-best-practices/references/component-suspense.md +228 -0
  14. package/skills/vue-best-practices/references/component-teleport.md +108 -0
  15. package/skills/vue-best-practices/references/component-transition-group.md +128 -0
  16. package/skills/vue-best-practices/references/component-transition.md +125 -0
  17. package/skills/vue-best-practices/references/composables.md +290 -0
  18. package/skills/vue-best-practices/references/directives.md +162 -0
  19. package/skills/vue-best-practices/references/perf-avoid-component-abstraction-in-lists.md +159 -0
  20. package/skills/vue-best-practices/references/perf-v-once-v-memo-directives.md +182 -0
  21. package/skills/vue-best-practices/references/perf-virtualize-large-lists.md +187 -0
  22. package/skills/vue-best-practices/references/plugins.md +166 -0
  23. package/skills/vue-best-practices/references/reactivity.md +346 -0
  24. package/skills/vue-best-practices/references/render-functions.md +201 -0
  25. package/skills/vue-best-practices/references/sfc.md +310 -0
  26. package/skills/vue-best-practices/references/state-management.md +135 -0
  27. package/skills/vue-best-practices/references/updated-hook-performance.md +187 -0
  28. package/skills/vue-debug-guides/SKILL.md +205 -0
  29. package/skills/vue-debug-guides/reference/animation-key-for-rerender.md +160 -0
  30. package/skills/vue-debug-guides/reference/animation-transitiongroup-performance.md +241 -0
  31. package/skills/vue-debug-guides/reference/async-component-error-handling.md +115 -0
  32. package/skills/vue-debug-guides/reference/async-component-keepalive-ref-issue.md +112 -0
  33. package/skills/vue-debug-guides/reference/async-component-suspense-control.md +84 -0
  34. package/skills/vue-debug-guides/reference/async-component-vue-router.md +109 -0
  35. package/skills/vue-debug-guides/reference/attrs-event-listener-merging.md +205 -0
  36. package/skills/vue-debug-guides/reference/checkbox-true-false-value-form-submission.md +118 -0
  37. package/skills/vue-debug-guides/reference/cleanup-side-effects.md +172 -0
  38. package/skills/vue-debug-guides/reference/click-events-on-components.md +180 -0
  39. package/skills/vue-debug-guides/reference/component-naming-conflicts.md +159 -0
  40. package/skills/vue-debug-guides/reference/component-ref-requires-defineexpose.md +176 -0
  41. package/skills/vue-debug-guides/reference/composable-avoid-hidden-side-effects.md +208 -0
  42. package/skills/vue-debug-guides/reference/composable-call-location-restrictions.md +141 -0
  43. package/skills/vue-debug-guides/reference/composable-naming-return-pattern.md +139 -0
  44. package/skills/vue-debug-guides/reference/composable-tovalue-inside-watcheffect.md +182 -0
  45. package/skills/vue-debug-guides/reference/composition-api-not-functional-programming.md +120 -0
  46. package/skills/vue-debug-guides/reference/composition-api-script-setup-async-context.md +203 -0
  47. package/skills/vue-debug-guides/reference/composition-api-vs-react-hooks-differences.md +156 -0
  48. package/skills/vue-debug-guides/reference/computed-array-mutation.md +148 -0
  49. package/skills/vue-debug-guides/reference/computed-conditional-dependencies.md +147 -0
  50. package/skills/vue-debug-guides/reference/computed-no-parameters.md +159 -0
  51. package/skills/vue-debug-guides/reference/computed-no-side-effects.md +107 -0
  52. package/skills/vue-debug-guides/reference/computed-return-value-readonly.md +160 -0
  53. package/skills/vue-debug-guides/reference/configure-app-before-mount.md +89 -0
  54. package/skills/vue-debug-guides/reference/declare-emits-for-documentation.md +212 -0
  55. package/skills/vue-debug-guides/reference/define-expose-before-await.md +192 -0
  56. package/skills/vue-debug-guides/reference/define-model-default-value-sync.md +139 -0
  57. package/skills/vue-debug-guides/reference/defineEmits-must-be-top-level.md +164 -0
  58. package/skills/vue-debug-guides/reference/defineEmits-no-runtime-and-type-mixed.md +170 -0
  59. package/skills/vue-debug-guides/reference/definemodel-object-mutation-no-emit.md +148 -0
  60. package/skills/vue-debug-guides/reference/dom-update-timing-nexttick.md +90 -0
  61. package/skills/vue-debug-guides/reference/dynamic-argument-constraints.md +146 -0
  62. package/skills/vue-debug-guides/reference/dynamic-component-registration-vite.md +147 -0
  63. package/skills/vue-debug-guides/reference/event-modifier-order-matters.md +101 -0
  64. package/skills/vue-debug-guides/reference/exact-modifier-for-precise-shortcuts.md +155 -0
  65. package/skills/vue-debug-guides/reference/fallthrough-attrs-overwrite-vue3.md +159 -0
  66. package/skills/vue-debug-guides/reference/in-dom-template-parsing-caveats.md +149 -0
  67. package/skills/vue-debug-guides/reference/inheritattrs-false-for-wrapper-components.md +230 -0
  68. package/skills/vue-debug-guides/reference/keepalive-router-nested-double-mount.md +222 -0
  69. package/skills/vue-debug-guides/reference/keepalive-transition-memory-leak.md +144 -0
  70. package/skills/vue-debug-guides/reference/keyup-modifier-timing.md +137 -0
  71. package/skills/vue-debug-guides/reference/lifecycle-dom-access-timing.md +216 -0
  72. package/skills/vue-debug-guides/reference/lifecycle-hooks-synchronous-registration.md +156 -0
  73. package/skills/vue-debug-guides/reference/lifecycle-ssr-awareness.md +184 -0
  74. package/skills/vue-debug-guides/reference/local-components-not-in-descendants.md +151 -0
  75. package/skills/vue-debug-guides/reference/mount-return-value.md +88 -0
  76. package/skills/vue-debug-guides/reference/multi-root-component-class-attrs.md +93 -0
  77. package/skills/vue-debug-guides/reference/native-event-collision-with-emits.md +162 -0
  78. package/skills/vue-debug-guides/reference/no-passive-with-prevent.md +141 -0
  79. package/skills/vue-debug-guides/reference/no-v-if-with-v-for.md +136 -0
  80. package/skills/vue-debug-guides/reference/perf-computed-object-stability.md +157 -0
  81. package/skills/vue-debug-guides/reference/perf-props-stability-update-optimization.md +140 -0
  82. package/skills/vue-debug-guides/reference/plugin-global-properties-sparingly.md +109 -0
  83. package/skills/vue-debug-guides/reference/plugin-install-before-mount.md +124 -0
  84. package/skills/vue-debug-guides/reference/plugin-prefer-provide-inject-over-global-properties.md +120 -0
  85. package/skills/vue-debug-guides/reference/plugin-typescript-type-augmentation.md +157 -0
  86. package/skills/vue-debug-guides/reference/prop-defineprops-scope-limitation.md +161 -0
  87. package/skills/vue-debug-guides/reference/provide-inject-debugging-challenges.md +203 -0
  88. package/skills/vue-debug-guides/reference/provide-inject-default-value-factory.md +244 -0
  89. package/skills/vue-debug-guides/reference/provide-inject-reactivity-not-automatic.md +226 -0
  90. package/skills/vue-debug-guides/reference/provide-inject-synchronous-setup.md +235 -0
  91. package/skills/vue-debug-guides/reference/reactive-destructuring.md +89 -0
  92. package/skills/vue-debug-guides/reference/reactivity-debugging-hooks.md +132 -0
  93. package/skills/vue-debug-guides/reference/reactivity-markraw-for-non-reactive.md +149 -0
  94. package/skills/vue-debug-guides/reference/reactivity-proxy-identity-hazard.md +96 -0
  95. package/skills/vue-debug-guides/reference/reactivity-same-tick-batching.md +166 -0
  96. package/skills/vue-debug-guides/reference/ref-value-access.md +61 -0
  97. package/skills/vue-debug-guides/reference/refs-in-collections-need-value.md +81 -0
  98. package/skills/vue-debug-guides/reference/render-function-avoid-internal-vnode-properties.md +151 -0
  99. package/skills/vue-debug-guides/reference/render-function-vnodes-must-be-unique.md +133 -0
  100. package/skills/vue-debug-guides/reference/rendering-render-function-h-import-vue3.md +148 -0
  101. package/skills/vue-debug-guides/reference/rendering-render-function-return-from-setup.md +148 -0
  102. package/skills/vue-debug-guides/reference/rendering-render-function-slots-as-functions.md +168 -0
  103. package/skills/vue-debug-guides/reference/rendering-resolve-component-for-string-names.md +231 -0
  104. package/skills/vue-debug-guides/reference/select-initial-value-ios-bug.md +91 -0
  105. package/skills/vue-debug-guides/reference/self-referencing-component-name.md +157 -0
  106. package/skills/vue-debug-guides/reference/sfc-named-exports-forbidden.md +184 -0
  107. package/skills/vue-debug-guides/reference/sfc-scoped-css-child-component-styling.md +156 -0
  108. package/skills/vue-debug-guides/reference/sfc-scoped-css-dynamic-content.md +193 -0
  109. package/skills/vue-debug-guides/reference/sfc-scoped-css-slot-content.md +242 -0
  110. package/skills/vue-debug-guides/reference/sfc-script-setup-reactivity.md +195 -0
  111. package/skills/vue-debug-guides/reference/slot-forwarding-to-child-components.md +143 -0
  112. package/skills/vue-debug-guides/reference/slot-implicit-default-content.md +155 -0
  113. package/skills/vue-debug-guides/reference/slot-name-reserved-prop.md +109 -0
  114. package/skills/vue-debug-guides/reference/slot-named-scoped-explicit-default.md +95 -0
  115. package/skills/vue-debug-guides/reference/slot-render-scope-parent-only.md +135 -0
  116. package/skills/vue-debug-guides/reference/slot-v-slot-on-components-or-templates-only.md +122 -0
  117. package/skills/vue-debug-guides/reference/ssr-hydration-mismatch-causes.md +280 -0
  118. package/skills/vue-debug-guides/reference/ssr-platform-specific-apis.md +256 -0
  119. package/skills/vue-debug-guides/reference/state-ssr-cross-request-pollution.md +276 -0
  120. package/skills/vue-debug-guides/reference/suspense-no-builtin-error-handling.md +127 -0
  121. package/skills/vue-debug-guides/reference/suspense-ssr-hydration-issues.md +159 -0
  122. package/skills/vue-debug-guides/reference/tailwind-dynamic-class-generation.md +144 -0
  123. package/skills/vue-debug-guides/reference/teleport-scoped-styles-limitation.md +191 -0
  124. package/skills/vue-debug-guides/reference/teleport-ssr-hydration.md +152 -0
  125. package/skills/vue-debug-guides/reference/teleport-target-must-exist.md +113 -0
  126. package/skills/vue-debug-guides/reference/template-expressions-restrictions.md +114 -0
  127. package/skills/vue-debug-guides/reference/template-functions-no-side-effects.md +187 -0
  128. package/skills/vue-debug-guides/reference/template-ref-null-with-v-if.md +123 -0
  129. package/skills/vue-debug-guides/reference/template-ref-unwrapping-top-level.md +104 -0
  130. package/skills/vue-debug-guides/reference/template-ref-v-for-order.md +172 -0
  131. package/skills/vue-debug-guides/reference/textarea-no-interpolation.md +72 -0
  132. package/skills/vue-debug-guides/reference/transition-group-flip-inline-elements.md +152 -0
  133. package/skills/vue-debug-guides/reference/transition-group-move-animation-position-absolute.md +130 -0
  134. package/skills/vue-debug-guides/reference/transition-group-no-default-wrapper-vue3.md +152 -0
  135. package/skills/vue-debug-guides/reference/transition-js-hooks-done-callback.md +251 -0
  136. package/skills/vue-debug-guides/reference/transition-nested-duration.md +182 -0
  137. package/skills/vue-debug-guides/reference/transition-reusable-scoped-style.md +245 -0
  138. package/skills/vue-debug-guides/reference/transition-router-view-appear.md +193 -0
  139. package/skills/vue-debug-guides/reference/transition-type-when-mixed.md +172 -0
  140. package/skills/vue-debug-guides/reference/transition-unmount-hook-timing.md +149 -0
  141. package/skills/vue-debug-guides/reference/ts-defineprops-boolean-default-false.md +225 -0
  142. package/skills/vue-debug-guides/reference/ts-defineprops-imported-types-limitations.md +281 -0
  143. package/skills/vue-debug-guides/reference/ts-event-handler-explicit-typing.md +213 -0
  144. package/skills/vue-debug-guides/reference/ts-reactive-no-generic-argument.md +196 -0
  145. package/skills/vue-debug-guides/reference/ts-shallowref-for-dynamic-components.md +218 -0
  146. package/skills/vue-debug-guides/reference/ts-template-ref-null-handling.md +249 -0
  147. package/skills/vue-debug-guides/reference/ts-template-type-casting.md +214 -0
  148. package/skills/vue-debug-guides/reference/ts-withdefaults-mutable-factory-function.md +171 -0
  149. package/skills/vue-debug-guides/reference/undeclared-emits-double-firing.md +195 -0
  150. package/skills/vue-debug-guides/reference/use-template-ref-vue35.md +158 -0
  151. package/skills/vue-debug-guides/reference/v-else-must-follow-v-if.md +136 -0
  152. package/skills/vue-debug-guides/reference/v-for-component-props.md +95 -0
  153. package/skills/vue-debug-guides/reference/v-for-computed-reverse-sort.md +86 -0
  154. package/skills/vue-debug-guides/reference/v-for-key-attribute.md +90 -0
  155. package/skills/vue-debug-guides/reference/v-for-range-starts-at-one.md +66 -0
  156. package/skills/vue-debug-guides/reference/v-if-null-check-order.md +171 -0
  157. package/skills/vue-debug-guides/reference/v-model-ignores-html-attributes.md +83 -0
  158. package/skills/vue-debug-guides/reference/v-model-ime-composition.md +83 -0
  159. package/skills/vue-debug-guides/reference/v-model-number-modifier-behavior.md +124 -0
  160. package/skills/vue-debug-guides/reference/v-show-template-limitation.md +124 -0
  161. package/skills/vue-debug-guides/reference/watch-async-cleanup.md +180 -0
  162. package/skills/vue-debug-guides/reference/watch-async-creation-memory-leak.md +176 -0
  163. package/skills/vue-debug-guides/reference/watch-deep-same-object-reference.md +165 -0
  164. package/skills/vue-debug-guides/reference/watch-flush-timing.md +189 -0
  165. package/skills/vue-debug-guides/reference/watch-reactive-property-getter.md +108 -0
  166. package/skills/vue-debug-guides/reference/watcheffect-async-dependency-tracking.md +173 -0
  167. package/skills/vue-debug-guides/reference/watcheffect-flush-post-for-refs.md +176 -0
  168. package/skills/vue-jsx-best-practices/SKILL.md +12 -0
  169. package/skills/vue-jsx-best-practices/reference/render-function-jsx-vue-vs-react.md +141 -0
  170. package/skills/vue-options-api-best-practices/SKILL.md +23 -0
  171. package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-lifecycle-hooks.md +95 -0
  172. package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-methods.md +68 -0
  173. package/skills/vue-options-api-best-practices/reference/stateful-methods-lifecycle.md +61 -0
  174. package/skills/vue-options-api-best-practices/reference/ts-options-api-arrow-functions-validators.md +141 -0
  175. package/skills/vue-options-api-best-practices/reference/ts-options-api-computed-return-types.md +192 -0
  176. package/skills/vue-options-api-best-practices/reference/ts-options-api-proptype-complex-types.md +212 -0
  177. package/skills/vue-options-api-best-practices/reference/ts-options-api-provide-inject-limitations.md +135 -0
  178. package/skills/vue-options-api-best-practices/reference/ts-options-api-type-event-handlers.md +202 -0
  179. package/skills/vue-options-api-best-practices/reference/ts-options-api-use-definecomponent.md +172 -0
  180. package/skills/vue-options-api-best-practices/reference/ts-strict-mode-options-api.md +197 -0
  181. package/skills/vue-pinia-best-practices/SKILL.md +21 -0
  182. package/skills/vue-pinia-best-practices/reference/pinia-no-active-pinia-error.md +248 -0
  183. package/skills/vue-pinia-best-practices/reference/pinia-setup-store-return-all-state.md +227 -0
  184. package/skills/vue-pinia-best-practices/reference/pinia-store-destructuring-breaks-reactivity.md +193 -0
  185. package/skills/vue-pinia-best-practices/reference/state-url-for-ephemeral-filters.md +238 -0
  186. package/skills/vue-pinia-best-practices/reference/state-use-pinia-for-large-apps.md +262 -0
  187. package/skills/vue-pinia-best-practices/reference/store-method-binding-parentheses.md +191 -0
  188. package/skills/vue-router-best-practices/SKILL.md +23 -0
  189. package/skills/vue-router-best-practices/reference/router-beforeenter-no-param-trigger.md +167 -0
  190. package/skills/vue-router-best-practices/reference/router-beforerouteenter-no-this.md +176 -0
  191. package/skills/vue-router-best-practices/reference/router-guard-async-await-pattern.md +227 -0
  192. package/skills/vue-router-best-practices/reference/router-navigation-guard-infinite-loop.md +187 -0
  193. package/skills/vue-router-best-practices/reference/router-navigation-guard-next-deprecated.md +150 -0
  194. package/skills/vue-router-best-practices/reference/router-param-change-no-lifecycle.md +181 -0
  195. package/skills/vue-router-best-practices/reference/router-simple-routing-cleanup.md +209 -0
  196. package/skills/vue-router-best-practices/reference/router-use-vue-router-for-production.md +183 -0
  197. package/skills/vue-testing-best-practices/SKILL.md +29 -0
  198. package/skills/vue-testing-best-practices/reference/async-component-testing.md +163 -0
  199. package/skills/vue-testing-best-practices/reference/teleport-testing-complexity.md +158 -0
  200. package/skills/vue-testing-best-practices/reference/testing-async-await-flushpromises.md +175 -0
  201. package/skills/vue-testing-best-practices/reference/testing-browser-vs-node-runners.md +208 -0
  202. package/skills/vue-testing-best-practices/reference/testing-component-blackbox-approach.md +144 -0
  203. package/skills/vue-testing-best-practices/reference/testing-composables-helper-wrapper.md +238 -0
  204. package/skills/vue-testing-best-practices/reference/testing-e2e-playwright-recommended.md +242 -0
  205. package/skills/vue-testing-best-practices/reference/testing-no-snapshot-only.md +197 -0
  206. package/skills/vue-testing-best-practices/reference/testing-pinia-store-setup.md +228 -0
  207. package/skills/vue-testing-best-practices/reference/testing-suspense-async-components.md +229 -0
  208. package/skills/vue-testing-best-practices/reference/testing-vitest-recommended-for-vue.md +204 -0
@@ -0,0 +1,95 @@
1
+ ---
2
+ title: Always Pass v-for Data to Components via Props
3
+ impact: MEDIUM
4
+ impactDescription: Components have isolated scope - v-for iteration data is not automatically available inside child components
5
+ type: gotcha
6
+ tags: [vue3, v-for, components, props, list-rendering]
7
+ ---
8
+
9
+ # Always Pass v-for Data to Components via Props
10
+
11
+ **Impact: MEDIUM** - Vue components have isolated scope by design. When using `v-for` to render components, the iteration variable (e.g., `item`) is NOT automatically available inside the child component. You must explicitly pass the data through props.
12
+
13
+ This isolation is intentional - it keeps components reusable and their data dependencies explicit. Forgetting to pass props results in `undefined` data or errors about missing properties.
14
+
15
+ ## Task Checklist
16
+
17
+ - [ ] Always bind iteration data to component props explicitly
18
+ - [ ] Pass both the item and index if the component needs them
19
+ - [ ] Always include a unique `:key` when rendering components with v-for
20
+ - [ ] Define corresponding props in the child component to receive the data
21
+
22
+ **Incorrect:**
23
+ ```html
24
+ <!-- WRONG: Component cannot access 'todo' - it's not in scope -->
25
+ <TodoItem v-for="todo in todos" :key="todo.id" />
26
+
27
+ <!-- Inside TodoItem.vue: this.todo or todo is undefined! -->
28
+ ```
29
+
30
+ ```html
31
+ <!-- WRONG: Key provided but no data passed -->
32
+ <UserCard
33
+ v-for="user in users"
34
+ :key="user.id"
35
+ />
36
+ <!-- UserCard has no user data to display -->
37
+ ```
38
+
39
+ **Correct:**
40
+ ```html
41
+ <!-- CORRECT: Explicitly pass the item as a prop -->
42
+ <TodoItem
43
+ v-for="todo in todos"
44
+ :key="todo.id"
45
+ :todo="todo"
46
+ />
47
+ ```
48
+
49
+ ```html
50
+ <!-- CORRECT: Pass multiple pieces of data -->
51
+ <UserCard
52
+ v-for="(user, index) in users"
53
+ :key="user.id"
54
+ :user="user"
55
+ :index="index"
56
+ :is-first="index === 0"
57
+ />
58
+ ```
59
+
60
+ ```vue
61
+ <!-- Child component: UserCard.vue -->
62
+ <script setup>
63
+ defineProps({
64
+ user: {
65
+ type: Object,
66
+ required: true
67
+ },
68
+ index: {
69
+ type: Number,
70
+ required: true
71
+ },
72
+ isFirst: {
73
+ type: Boolean,
74
+ default: false
75
+ }
76
+ })
77
+ </script>
78
+
79
+ <template>
80
+ <div class="user-card">
81
+ <span>{{ index + 1 }}. {{ user.name }}</span>
82
+ <span v-if="isFirst">(First User)</span>
83
+ </div>
84
+ </template>
85
+ ```
86
+
87
+ ## Why Explicit Props?
88
+
89
+ 1. **Clear data flow**: Makes dependencies explicit and traceable
90
+ 2. **Reusability**: Components work anywhere, not just inside specific v-for loops
91
+ 3. **Type safety**: Props can be validated with type and required checks
92
+ 4. **Maintainability**: Easier to understand what data a component needs
93
+
94
+ ## Reference
95
+ - [Vue.js List Rendering - v-for with Components](https://vuejs.org/guide/essentials/list.html#v-for-with-a-component)
@@ -0,0 +1,86 @@
1
+ ---
2
+ title: Copy Arrays Before reverse() or sort() in Computed Properties
3
+ impact: MEDIUM
4
+ impactDescription: reverse() and sort() mutate the original array, causing unintended side effects in computed getters
5
+ type: gotcha
6
+ tags: [vue3, v-for, computed, array, mutation, list-rendering]
7
+ ---
8
+
9
+ # Copy Arrays Before reverse() or sort() in Computed Properties
10
+
11
+ **Impact: MEDIUM** - The `reverse()` and `sort()` methods mutate the original array in-place. When used directly in a computed property getter, this causes the source array to be modified, leading to infinite reactivity loops or incorrect data state.
12
+
13
+ Computed properties should be pure - they calculate a value without side effects. Mutating the source data inside a computed getter violates this principle and causes unpredictable behavior.
14
+
15
+ ## Task Checklist
16
+
17
+ - [ ] Always create a copy of the array before calling `reverse()` or `sort()` in computed properties
18
+ - [ ] Use spread operator `[...array]` or `Array.from(array)` or `array.slice()` to copy
19
+ - [ ] This applies to any in-place mutation method used in computed getters
20
+ - [ ] Consider using `toSorted()` and `toReversed()` (ES2023) which return new arrays
21
+
22
+ **Incorrect:**
23
+ ```javascript
24
+ const numbers = ref([1, 2, 3, 4, 5])
25
+
26
+ // WRONG: Mutates the original array
27
+ const reversedNumbers = computed(() => {
28
+ return numbers.value.reverse() // Modifies numbers.value!
29
+ })
30
+
31
+ // WRONG: Same issue with sort
32
+ const sortedItems = computed(() => {
33
+ return items.value.sort((a, b) => a.name.localeCompare(b.name))
34
+ })
35
+ ```
36
+
37
+ **Correct:**
38
+ ```javascript
39
+ const numbers = ref([1, 2, 3, 4, 5])
40
+
41
+ // CORRECT: Create a copy first with spread operator
42
+ const reversedNumbers = computed(() => {
43
+ return [...numbers.value].reverse()
44
+ })
45
+
46
+ // CORRECT: Create a copy before sorting
47
+ const sortedItems = computed(() => {
48
+ return [...items.value].sort((a, b) => a.name.localeCompare(b.name))
49
+ })
50
+
51
+ // CORRECT: Using slice() to copy
52
+ const reversedNumbers = computed(() => {
53
+ return numbers.value.slice().reverse()
54
+ })
55
+
56
+ // CORRECT: ES2023 non-mutating methods (if supported)
57
+ const reversedNumbers = computed(() => {
58
+ return numbers.value.toReversed()
59
+ })
60
+
61
+ const sortedItems = computed(() => {
62
+ return items.value.toSorted((a, b) => a.price - b.price)
63
+ })
64
+ ```
65
+
66
+ ## Also Applies to Methods Used in Templates
67
+
68
+ When using methods to filter/sort in nested v-for loops, the same rule applies:
69
+
70
+ ```javascript
71
+ // CORRECT: Method that doesn't mutate
72
+ function getSortedChildren(parent) {
73
+ return [...parent.children].sort((a, b) => a.order - b.order)
74
+ }
75
+ ```
76
+
77
+ ```html
78
+ <ul v-for="parent in parents" :key="parent.id">
79
+ <li v-for="child in getSortedChildren(parent)" :key="child.id">
80
+ {{ child.name }}
81
+ </li>
82
+ </ul>
83
+ ```
84
+
85
+ ## Reference
86
+ - [Vue.js List Rendering - Displaying Filtered/Sorted Results](https://vuejs.org/guide/essentials/list.html#displaying-filtered-sorted-results)
@@ -0,0 +1,90 @@
1
+ ---
2
+ title: Always Provide Unique Keys in v-for Loops
3
+ impact: HIGH
4
+ impactDescription: Missing or improper keys cause hard-to-debug bugs when list items have state, components, or animations
5
+ type: gotcha
6
+ tags: [vue3, v-for, list-rendering, key, state, components]
7
+ ---
8
+
9
+ # Always Provide Unique Keys in v-for Loops
10
+
11
+ **Impact: HIGH** - Without proper keys, Vue cannot track element identity when lists change. This causes component state loss, incorrect animations, form input values jumping between items, and bugs that are extremely difficult to debug.
12
+
13
+ The `key` attribute tells Vue how your data relates to the DOM elements it renders. When data ordering changes (via sort, filter, add, or remove), Vue uses keys to determine what to update, remove, or create. Without unique keys, Vue reuses DOM elements in-place which can cause one item's state to incorrectly appear on another item.
14
+
15
+ ## Task Checklist
16
+
17
+ - [ ] Always provide `:key` with unique, stable identifiers (database IDs, UUIDs)
18
+ - [ ] Never use array index as key - indices shift when items are added/removed
19
+ - [ ] Use primitive values only (strings or numbers) - never use objects as keys
20
+ - [ ] On `<template v-for>`, place the key on the `<template>` tag itself (Vue 3 change)
21
+ - [ ] When using components in v-for, keys are mandatory, not optional
22
+
23
+ **Incorrect:**
24
+ ```html
25
+ <!-- WRONG: No key provided -->
26
+ <li v-for="item in items">{{ item.name }}</li>
27
+
28
+ <!-- WRONG: Using array index as key - shifts when list changes -->
29
+ <li v-for="(item, index) in items" :key="index">
30
+ <input v-model="item.value" />
31
+ </li>
32
+
33
+ <!-- WRONG: Object as key -->
34
+ <li v-for="item in items" :key="item">{{ item.name }}</li>
35
+
36
+ <!-- WRONG (Vue 3): Key on child instead of template -->
37
+ <template v-for="item in items">
38
+ <li :key="item.id">{{ item.name }}</li>
39
+ </template>
40
+ ```
41
+
42
+ ```javascript
43
+ // Bug demonstration: Using index as key
44
+ // Initial: ['Alice', 'Bob', 'Charlie'] at indices [0, 1, 2]
45
+ // After removing 'Bob': ['Alice', 'Charlie'] at indices [0, 1]
46
+ // Charlie now has index 1, so Vue reuses Bob's DOM/component state for Charlie!
47
+ ```
48
+
49
+ **Correct:**
50
+ ```html
51
+ <!-- CORRECT: Unique identifier as key -->
52
+ <li v-for="item in items" :key="item.id">
53
+ {{ item.name }}
54
+ </li>
55
+
56
+ <!-- CORRECT: With components -->
57
+ <MyComponent
58
+ v-for="item in items"
59
+ :key="item.id"
60
+ :item="item"
61
+ />
62
+
63
+ <!-- CORRECT (Vue 3): Key on template tag -->
64
+ <template v-for="item in items" :key="item.id">
65
+ <li>{{ item.name }}</li>
66
+ <span>{{ item.description }}</span>
67
+ </template>
68
+
69
+ <!-- CORRECT: With stateful elements -->
70
+ <div v-for="user in users" :key="user.id">
71
+ <input v-model="user.email" />
72
+ <select v-model="user.role">
73
+ <option value="admin">Admin</option>
74
+ <option value="user">User</option>
75
+ </select>
76
+ </div>
77
+ ```
78
+
79
+ ## When Keys Are Critical
80
+
81
+ Keys are absolutely required when v-for loops contain:
82
+ - Components with local state
83
+ - Form elements (`<input>`, `<select>`, `<textarea>`)
84
+ - Elements with initialization logic (mounted/created hooks)
85
+ - Animations or transitions
86
+ - Direct DOM manipulation
87
+
88
+ ## Reference
89
+ - [Vue.js List Rendering - Key](https://vuejs.org/guide/essentials/list.html#maintaining-state-with-key)
90
+ - [Vue 3 Migration Guide - Key on Template](https://v3-migration.vuejs.org/breaking-changes/key-attribute)
@@ -0,0 +1,66 @@
1
+ ---
2
+ title: v-for Range Iteration Starts at 1, Not 0
3
+ impact: LOW
4
+ impactDescription: v-for with a number range starts at 1, unlike JavaScript arrays which start at 0
5
+ type: gotcha
6
+ tags: [vue3, v-for, list-rendering, range]
7
+ ---
8
+
9
+ # v-for Range Iteration Starts at 1, Not 0
10
+
11
+ **Impact: LOW** - When using `v-for` with a number (range iteration), the iteration starts at `1`, not `0`. This differs from typical JavaScript behavior where arrays are 0-indexed.
12
+
13
+ This gotcha commonly causes off-by-one errors when the generated numbers are used for calculations or array indexing.
14
+
15
+ ## Task Checklist
16
+
17
+ - [ ] Remember `v-for="n in 10"` produces 1 through 10, not 0 through 9
18
+ - [ ] When using range values for array indexing, subtract 1: `items[n - 1]`
19
+ - [ ] Consider creating a computed array if you need 0-based indices
20
+
21
+ **Incorrect Assumption:**
22
+ ```html
23
+ <!-- Developer expects 0-9, but gets 1-10 -->
24
+ <span v-for="n in 10">{{ n }}</span>
25
+ <!-- Output: 1 2 3 4 5 6 7 8 9 10 -->
26
+
27
+ <!-- WRONG: Off-by-one error when used for array access -->
28
+ <li v-for="n in items.length" :key="n">
29
+ {{ items[n].name }} <!-- Error! items[10] is undefined when length is 10 -->
30
+ </li>
31
+ ```
32
+
33
+ **Correct:**
34
+ ```html
35
+ <!-- Correct understanding: 1-based range -->
36
+ <span v-for="n in 10" :key="n">{{ n }}</span>
37
+ <!-- Output: 1 2 3 4 5 6 7 8 9 10 -->
38
+
39
+ <!-- CORRECT: Adjust index for array access -->
40
+ <li v-for="n in items.length" :key="n">
41
+ {{ items[n - 1].name }} <!-- n-1 converts to 0-based -->
42
+ </li>
43
+
44
+ <!-- BETTER: Just iterate the array directly -->
45
+ <li v-for="(item, index) in items" :key="item.id">
46
+ {{ index + 1 }}. {{ item.name }} <!-- index is 0-based, add 1 for display -->
47
+ </li>
48
+ ```
49
+
50
+ ```html
51
+ <!-- Range for repeating elements (no array involved) -->
52
+ <div v-for="n in 3" :key="n" class="skeleton-row">
53
+ Loading placeholder {{ n }} of 3...
54
+ </div>
55
+ <!-- Output: Loading placeholder 1 of 3, 2 of 3, 3 of 3 -->
56
+ ```
57
+
58
+ ## When Range Iteration Is Useful
59
+
60
+ - Rendering a fixed number of placeholder/skeleton elements
61
+ - Creating pagination buttons: `v-for="page in totalPages"`
62
+ - Generating star ratings: `v-for="star in 5"`
63
+ - Repeating template structures a set number of times
64
+
65
+ ## Reference
66
+ - [Vue.js List Rendering - v-for with a Range](https://vuejs.org/guide/essentials/list.html#v-for-with-a-range)
@@ -0,0 +1,171 @@
1
+ ---
2
+ title: Check for Null/Undefined Before Accessing Properties in v-if
3
+ impact: MEDIUM
4
+ impactDescription: Accessing properties on null/undefined causes runtime errors and crashes
5
+ type: capability
6
+ tags: [vue3, conditional-rendering, v-if, null-check, defensive-programming]
7
+ ---
8
+
9
+ # Check for Null/Undefined Before Accessing Properties in v-if
10
+
11
+ **Impact: MEDIUM** - Accessing properties on null or undefined objects in `v-if` conditions causes "Cannot read property of undefined" runtime errors. This commonly occurs when data is loaded asynchronously or when optional object properties are accessed without null checks.
12
+
13
+ ## Task Checklist
14
+
15
+ - [ ] Always check that an object exists before accessing its properties
16
+ - [ ] Use optional chaining (?.) in Vue 3 templates for cleaner null checks
17
+ - [ ] Consider using computed properties for complex conditional logic
18
+ - [ ] Handle loading states explicitly rather than relying on undefined checks
19
+
20
+ **Incorrect:**
21
+ ```html
22
+ <!-- WRONG: Accessing property before checking object exists -->
23
+ <template>
24
+ <div v-if="user.isAdmin">
25
+ Admin Panel
26
+ </div>
27
+ <!-- Error if user is null/undefined: Cannot read property 'isAdmin' of undefined -->
28
+ </template>
29
+ ```
30
+
31
+ ```html
32
+ <!-- WRONG: Nested property access without checks -->
33
+ <template>
34
+ <div v-if="order.customer.address.city === 'NYC'">
35
+ Local delivery available
36
+ </div>
37
+ <!-- Error if any level is undefined -->
38
+ </template>
39
+ ```
40
+
41
+ ```html
42
+ <!-- WRONG: Array access without existence check -->
43
+ <template>
44
+ <div v-if="items[0].name === 'Featured'">
45
+ {{ items[0].description }}
46
+ </div>
47
+ <!-- Error if items is empty array -->
48
+ </template>
49
+ ```
50
+
51
+ **Correct:**
52
+ ```html
53
+ <!-- CORRECT: Check object exists first with && -->
54
+ <template>
55
+ <div v-if="user && user.isAdmin">
56
+ Admin Panel
57
+ </div>
58
+ </template>
59
+ ```
60
+
61
+ ```html
62
+ <!-- CORRECT: Optional chaining (Vue 3) -->
63
+ <template>
64
+ <div v-if="user?.isAdmin">
65
+ Admin Panel
66
+ </div>
67
+ </template>
68
+ ```
69
+
70
+ ```html
71
+ <!-- CORRECT: Optional chaining for nested properties -->
72
+ <template>
73
+ <div v-if="order?.customer?.address?.city === 'NYC'">
74
+ Local delivery available
75
+ </div>
76
+ </template>
77
+ ```
78
+
79
+ ```html
80
+ <!-- CORRECT: Array length check before access -->
81
+ <template>
82
+ <div v-if="items.length > 0 && items[0].name === 'Featured'">
83
+ {{ items[0].description }}
84
+ </div>
85
+
86
+ <!-- Or with optional chaining -->
87
+ <div v-if="items?.[0]?.name === 'Featured'">
88
+ {{ items[0].description }}
89
+ </div>
90
+ </template>
91
+ ```
92
+
93
+ ```html
94
+ <!-- CORRECT: Explicit loading state handling -->
95
+ <template>
96
+ <div v-if="isLoading">Loading...</div>
97
+ <div v-else-if="error">Error: {{ error.message }}</div>
98
+ <div v-else-if="user">
99
+ <h1>Welcome, {{ user.name }}</h1>
100
+ <div v-if="user.isAdmin">Admin Panel</div>
101
+ </div>
102
+ <div v-else>No user data</div>
103
+ </template>
104
+ ```
105
+
106
+ ## Using Computed Properties for Complex Checks
107
+
108
+ ```javascript
109
+ // CORRECT: Move complex checks to computed properties
110
+ <script setup>
111
+ import { computed } from 'vue'
112
+
113
+ const props = defineProps(['user', 'permissions'])
114
+
115
+ const canAccessAdmin = computed(() => {
116
+ return props.user?.isAdmin &&
117
+ props.permissions?.includes('admin_panel') &&
118
+ !props.user?.isDisabled
119
+ })
120
+
121
+ const userDisplayName = computed(() => {
122
+ return props.user?.profile?.displayName ||
123
+ props.user?.name ||
124
+ 'Anonymous'
125
+ })
126
+ </script>
127
+
128
+ <template>
129
+ <div v-if="canAccessAdmin">
130
+ Admin Panel
131
+ </div>
132
+ <span>{{ userDisplayName }}</span>
133
+ </template>
134
+ ```
135
+
136
+ ## Common Async Data Pattern
137
+
138
+ ```javascript
139
+ // CORRECT: Handle async data loading properly
140
+ <script setup>
141
+ import { ref, onMounted } from 'vue'
142
+
143
+ const user = ref(null)
144
+ const isLoading = ref(true)
145
+ const error = ref(null)
146
+
147
+ onMounted(async () => {
148
+ try {
149
+ user.value = await fetchUser()
150
+ } catch (e) {
151
+ error.value = e
152
+ } finally {
153
+ isLoading.value = false
154
+ }
155
+ })
156
+ </script>
157
+
158
+ <template>
159
+ <div v-if="isLoading">Loading user...</div>
160
+ <div v-else-if="error">Failed to load user</div>
161
+ <div v-else-if="user">
162
+ <!-- Safe to access user properties here -->
163
+ <h1>{{ user.name }}</h1>
164
+ <p v-if="user.bio">{{ user.bio }}</p>
165
+ </div>
166
+ </template>
167
+ ```
168
+
169
+ ## Reference
170
+ - [Vue.js Conditional Rendering](https://vuejs.org/guide/essentials/conditional.html)
171
+ - [MDN - Optional Chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining)
@@ -0,0 +1,83 @@
1
+ ---
2
+ title: v-model Ignores Initial HTML Attributes
3
+ impact: HIGH
4
+ impactDescription: v-model ignores value, checked, and selected HTML attributes - initial state must be set in JavaScript
5
+ type: capability
6
+ tags: [vue3, v-model, forms, input, checkbox, select, initialization]
7
+ ---
8
+
9
+ # v-model Ignores Initial HTML Attributes
10
+
11
+ **Impact: HIGH** - Setting initial values via HTML `value`, `checked`, or `selected` attributes has no effect when using v-model. The form will appear empty or in an unexpected state, confusing users and potentially causing data loss.
12
+
13
+ Vue's v-model always treats the bound JavaScript state as the single source of truth. Any initial attributes in the HTML are completely ignored. This is a common mistake when migrating from plain HTML forms or when copying HTML templates.
14
+
15
+ ## Task Checklist
16
+
17
+ - [ ] Never rely on HTML `value`, `checked`, or `selected` attributes when using v-model
18
+ - [ ] Always declare initial values in JavaScript using `ref()` or `reactive()`
19
+ - [ ] When migrating plain HTML forms to Vue, move all default values to JavaScript state
20
+ - [ ] Audit existing forms for hardcoded HTML default values that may be silently ignored
21
+
22
+ **Incorrect:**
23
+ ```html
24
+ <script setup>
25
+ import { ref } from 'vue'
26
+
27
+ const username = ref('') // Empty!
28
+ const isSubscribed = ref(false) // Not checked!
29
+ const country = ref('') // No default selection!
30
+ </script>
31
+
32
+ <template>
33
+ <!-- WRONG: These HTML attributes are completely ignored -->
34
+ <input v-model="username" value="default_user">
35
+
36
+ <input type="checkbox" v-model="isSubscribed" checked>
37
+
38
+ <select v-model="country">
39
+ <option value="us" selected>United States</option>
40
+ <option value="uk">United Kingdom</option>
41
+ </select>
42
+ </template>
43
+ ```
44
+
45
+ **Correct:**
46
+ ```html
47
+ <script setup>
48
+ import { ref } from 'vue'
49
+
50
+ // CORRECT: Set initial values in JavaScript
51
+ const username = ref('default_user')
52
+ const isSubscribed = ref(true)
53
+ const country = ref('us')
54
+ </script>
55
+
56
+ <template>
57
+ <!-- HTML attributes not needed - JavaScript state controls everything -->
58
+ <input v-model="username">
59
+
60
+ <input type="checkbox" v-model="isSubscribed">
61
+
62
+ <select v-model="country">
63
+ <option value="us">United States</option>
64
+ <option value="uk">United Kingdom</option>
65
+ </select>
66
+ </template>
67
+ ```
68
+
69
+ ```javascript
70
+ // Options API equivalent
71
+ export default {
72
+ data() {
73
+ return {
74
+ username: 'default_user',
75
+ isSubscribed: true,
76
+ country: 'us'
77
+ }
78
+ }
79
+ }
80
+ ```
81
+
82
+ ## Reference
83
+ - [Vue.js Form Input Bindings](https://vuejs.org/guide/essentials/forms.html)
@@ -0,0 +1,83 @@
1
+ ---
2
+ title: v-model Does Not Update During IME Composition
3
+ impact: MEDIUM
4
+ impactDescription: v-model won't capture intermediate input for Chinese, Japanese, Korean and other IME languages
5
+ type: capability
6
+ tags: [vue3, v-model, forms, input, ime, internationalization, i18n, cjk]
7
+ ---
8
+
9
+ # v-model Does Not Update During IME Composition
10
+
11
+ **Impact: MEDIUM** - When users type in languages that require an Input Method Editor (Chinese, Japanese, Korean, etc.), v-model won't update until the composition is complete. This breaks real-time validation, character counters, and live search features for international users.
12
+
13
+ IME (Input Method Editor) allows users to compose complex characters by typing multiple keystrokes. During this composition phase, v-model deliberately waits until the user confirms their selection before updating. This is usually desired, but can break features that need every keystroke.
14
+
15
+ ## Task Checklist
16
+
17
+ - [ ] Test forms with IME input if your app serves CJK (Chinese, Japanese, Korean) users
18
+ - [ ] For real-time features (live search, character counters), use manual event binding instead of v-model
19
+ - [ ] Consider both behaviors when designing - sometimes waiting for composition completion IS correct
20
+ - [ ] Document expected behavior for international users
21
+
22
+ **Problem - v-model waits for composition:**
23
+ ```html
24
+ <script setup>
25
+ import { ref } from 'vue'
26
+
27
+ const searchQuery = ref('')
28
+ const charCount = ref(0)
29
+ </script>
30
+
31
+ <template>
32
+ <!-- PROBLEM: During IME composition, searchQuery won't update -->
33
+ <!-- Chinese user types "ni hao" -> sees no results until they press space/enter -->
34
+ <input v-model="searchQuery" placeholder="Live search...">
35
+ <p>{{ searchQuery.length }} characters</p>
36
+
37
+ <!-- Character counter stays at 0 during IME input -->
38
+ </template>
39
+ ```
40
+
41
+ **Solution - Manual event binding for real-time updates:**
42
+ ```html
43
+ <script setup>
44
+ import { ref } from 'vue'
45
+
46
+ const searchQuery = ref('')
47
+
48
+ // This captures EVERY input event, including during IME composition
49
+ function handleInput(event) {
50
+ searchQuery.value = event.target.value
51
+ }
52
+ </script>
53
+
54
+ <template>
55
+ <!-- CORRECT: Manual binding captures all input, including IME composition -->
56
+ <input
57
+ :value="searchQuery"
58
+ @input="handleInput"
59
+ placeholder="Live search..."
60
+ >
61
+ <p>{{ searchQuery.length }} characters</p>
62
+ </template>
63
+ ```
64
+
65
+ ```html
66
+ <!-- Shorter inline version -->
67
+ <input
68
+ :value="searchQuery"
69
+ @input="event => searchQuery = event.target.value"
70
+ >
71
+ ```
72
+
73
+ **When v-model behavior IS correct:**
74
+ ```html
75
+ <!-- For form submission, waiting for composition IS usually better -->
76
+ <!-- User expects to confirm their character selection before it's "official" -->
77
+ <input v-model="formName" placeholder="Enter your name">
78
+
79
+ <!-- The final composed characters will be submitted, not intermediate states -->
80
+ ```
81
+
82
+ ## Reference
83
+ - [Vue.js Form Input Bindings](https://vuejs.org/guide/essentials/forms.html)