@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,144 @@
1
+ ---
2
+ title: KeepAlive with Transition Memory Leak
3
+ impact: MEDIUM
4
+ impactDescription: Combining KeepAlive with Transition can cause memory leaks in certain Vue versions
5
+ type: gotcha
6
+ tags: [vue3, keepalive, transition, memory-leak, animation]
7
+ ---
8
+
9
+ # KeepAlive with Transition Memory Leak
10
+
11
+ **Impact: MEDIUM** - There is a known memory leak when using `<Transition>` and `<KeepAlive>` together. Component instances may not be properly freed from memory when combining these features.
12
+
13
+ ## Task Checklist
14
+
15
+ - [ ] Test memory behavior when using KeepAlive + Transition together
16
+ - [ ] Consider if transition animation is necessary with cached components
17
+ - [ ] Use browser DevTools Memory tab to verify no leak
18
+ - [ ] Keep Vue updated to get latest bug fixes
19
+
20
+ ## The Problem
21
+
22
+ ```vue
23
+ <template>
24
+ <!-- Known memory leak combination in some Vue versions -->
25
+ <Transition name="fade">
26
+ <KeepAlive>
27
+ <component :is="currentView" />
28
+ </KeepAlive>
29
+ </Transition>
30
+ </template>
31
+ ```
32
+
33
+ When switching between components repeatedly:
34
+ - Component instances accumulate in memory
35
+ - References prevent garbage collection
36
+ - Memory usage grows with each switch
37
+
38
+ ## Diagnosis
39
+
40
+ Use Chrome DevTools to detect the leak:
41
+
42
+ 1. Open DevTools > Memory tab
43
+ 2. Take heap snapshot
44
+ 3. Switch between components 10+ times
45
+ 4. Take another heap snapshot
46
+ 5. Compare: look for growing VueComponent count
47
+
48
+ ## Workarounds
49
+
50
+ ### Option 1: Remove Transition if Not Essential
51
+
52
+ ```vue
53
+ <template>
54
+ <!-- No memory leak without Transition -->
55
+ <KeepAlive :max="5">
56
+ <component :is="currentView" />
57
+ </KeepAlive>
58
+ </template>
59
+ ```
60
+
61
+ ### Option 2: Use CSS Animations Instead
62
+
63
+ ```vue
64
+ <template>
65
+ <KeepAlive :max="5">
66
+ <component
67
+ :is="currentView"
68
+ :class="{ 'fade-enter': isTransitioning }"
69
+ />
70
+ </KeepAlive>
71
+ </template>
72
+
73
+ <style>
74
+ .fade-enter {
75
+ animation: fadeIn 0.3s ease-in;
76
+ }
77
+
78
+ @keyframes fadeIn {
79
+ from { opacity: 0; }
80
+ to { opacity: 1; }
81
+ }
82
+ </style>
83
+ ```
84
+
85
+ ### Option 3: Use Strict Cache Limits
86
+
87
+ If you must use both, minimize impact with strict limits:
88
+
89
+ ```vue
90
+ <template>
91
+ <Transition name="fade" mode="out-in">
92
+ <KeepAlive :max="3">
93
+ <component :is="currentView" />
94
+ </KeepAlive>
95
+ </Transition>
96
+ </template>
97
+ ```
98
+
99
+ ### Option 4: Key-Based Cache Invalidation
100
+
101
+ Force fresh instances when needed:
102
+
103
+ ```vue
104
+ <script setup>
105
+ import { ref, computed } from 'vue'
106
+
107
+ const currentView = ref('Dashboard')
108
+ const cacheKey = ref(0)
109
+
110
+ function switchViewFresh(view) {
111
+ currentView.value = view
112
+ cacheKey.value++ // Force new instance
113
+ }
114
+ </script>
115
+
116
+ <template>
117
+ <Transition name="fade" mode="out-in">
118
+ <KeepAlive :max="3">
119
+ <component :is="currentView" :key="cacheKey" />
120
+ </KeepAlive>
121
+ </Transition>
122
+ </template>
123
+ ```
124
+
125
+ ## Keep Vue Updated
126
+
127
+ This is a known issue tracked in Vue's GitHub repository. Memory leak fixes are periodically released, so ensure you're on the latest Vue version:
128
+
129
+ ```bash
130
+ npm update vue
131
+ ```
132
+
133
+ ## Key Points
134
+
135
+ 1. **Known issue** - Memory leaks with KeepAlive + Transition are documented
136
+ 2. **Test in DevTools** - Use Memory tab to verify your specific usage
137
+ 3. **Consider alternatives** - CSS animations may work without the leak
138
+ 4. **Set strict `max`** - Limit cache size to cap memory impact
139
+ 5. **Keep Vue updated** - Bug fixes are released periodically
140
+
141
+ ## Reference
142
+ - [GitHub Issue #9842: Memory leak with transition and keep-alive](https://github.com/vuejs/vue/issues/9842)
143
+ - [GitHub Issue #9840: Memory leak with transition and keep-alive](https://github.com/vuejs/vue/issues/9840)
144
+ - [Vue.js KeepAlive Documentation](https://vuejs.org/guide/built-ins/keep-alive.html)
@@ -0,0 +1,137 @@
1
+ ---
2
+ title: System Modifier Keys Must Be Held During keyup Events
3
+ impact: MEDIUM
4
+ impactDescription: Modifier keys (ctrl, alt, shift, meta) behave differently with keyup - they must be held when the key is released
5
+ type: gotcha
6
+ tags: [vue3, events, keyboard, modifiers, keyup, shortcuts]
7
+ ---
8
+
9
+ # System Modifier Keys Must Be Held During keyup Events
10
+
11
+ **Impact: MEDIUM** - When using system modifier keys (`.ctrl`, `.alt`, `.shift`, `.meta`) with `keyup` events, the modifier must still be pressed when the other key is released. Releasing the modifier key first will not trigger the event, causing keyboard shortcuts to appear broken.
12
+
13
+ ## Task Checklist
14
+
15
+ - [ ] Understand that `@keyup.ctrl` requires Ctrl to be held while releasing another key
16
+ - [ ] Consider using `keydown` instead of `keyup` for modifier key combinations
17
+ - [ ] Use `.exact` when you need precise modifier key control
18
+ - [ ] Test keyboard shortcuts with proper key release order
19
+
20
+ **Incorrect:**
21
+ ```html
22
+ <!-- WRONG: Expecting this to fire when Ctrl is released -->
23
+ <template>
24
+ <input @keyup.ctrl="onCtrlRelease" />
25
+ <!-- This does NOT fire when you just release Ctrl! -->
26
+ <!-- It fires when you release ANY key while holding Ctrl -->
27
+ </template>
28
+ ```
29
+
30
+ ```html
31
+ <!-- WRONG: Misunderstanding keyup.ctrl behavior -->
32
+ <template>
33
+ <div @keyup.ctrl="handleShortcut">
34
+ <!-- User presses Ctrl+S, releases Ctrl first, then S -->
35
+ <!-- Event does NOT fire because Ctrl wasn't held during S release -->
36
+ </div>
37
+ </template>
38
+ ```
39
+
40
+ **Correct:**
41
+ ```html
42
+ <!-- CORRECT: User must hold Ctrl while releasing another key -->
43
+ <template>
44
+ <input @keyup.ctrl.s="saveDocument" />
45
+ <!-- User presses Ctrl+S, then releases S while holding Ctrl -->
46
+ <!-- Event fires correctly -->
47
+ </template>
48
+
49
+ <script setup>
50
+ function saveDocument(event) {
51
+ event.preventDefault()
52
+ // Save logic here
53
+ }
54
+ </script>
55
+ ```
56
+
57
+ ```html
58
+ <!-- CORRECT: Use keydown for more intuitive modifier behavior -->
59
+ <template>
60
+ <div @keydown.ctrl.s="saveDocument">
61
+ <!-- keydown fires immediately when both keys are pressed -->
62
+ <!-- More intuitive for keyboard shortcuts -->
63
+ </div>
64
+ </template>
65
+ ```
66
+
67
+ ```html
68
+ <!-- CORRECT: Use .exact for precise modifier control -->
69
+ <template>
70
+ <!-- Only fires when ONLY Ctrl is pressed (no Shift, Alt, etc.) -->
71
+ <button @click.ctrl.exact="onCtrlClick">Ctrl+Click Only</button>
72
+
73
+ <!-- Fires with no system modifiers at all -->
74
+ <button @click.exact="onPlainClick">Plain Click Only</button>
75
+ </template>
76
+ ```
77
+
78
+ ## How System Modifiers Work with keyup
79
+
80
+ ```javascript
81
+ // Timeline of Ctrl+S keydown:
82
+ // 1. User presses Ctrl (keydown fires)
83
+ // 2. User presses S while holding Ctrl (keydown fires)
84
+
85
+ // Timeline of Ctrl+S keyup:
86
+ // 3. User releases S while holding Ctrl (keyup.ctrl.s fires!)
87
+ // 4. User releases Ctrl (keyup fires, but not keyup.ctrl.s)
88
+
89
+ // Common mistake:
90
+ // 3. User releases Ctrl first (nothing fires for our handler)
91
+ // 4. User releases S (keyup.s fires, but not keyup.ctrl.s)
92
+ ```
93
+
94
+ ## System Modifier Keys
95
+
96
+ ```html
97
+ <!-- Available system modifiers -->
98
+ <input @keyup.ctrl="..." /> <!-- Ctrl key -->
99
+ <input @keyup.alt="..." /> <!-- Alt key (Option on Mac) -->
100
+ <input @keyup.shift="..." /> <!-- Shift key -->
101
+ <input @keyup.meta="..." /> <!-- Cmd on Mac, Windows key on PC -->
102
+ ```
103
+
104
+ ## The .exact Modifier
105
+
106
+ ```html
107
+ <!-- Different .exact behaviors -->
108
+
109
+ <!-- Fires even if Shift/Alt are also pressed -->
110
+ <button @click.ctrl="onClick">Ctrl + any other modifiers</button>
111
+
112
+ <!-- Fires ONLY when Ctrl alone is pressed -->
113
+ <button @click.ctrl.exact="onClick">Ctrl only, no other modifiers</button>
114
+
115
+ <!-- Fires ONLY when no system modifiers are pressed -->
116
+ <button @click.exact="onClick">No modifiers allowed</button>
117
+ ```
118
+
119
+ ## Best Practice: Prefer keydown for Shortcuts
120
+
121
+ ```html
122
+ <template>
123
+ <div
124
+ tabindex="0"
125
+ @keydown.ctrl.s.prevent="save"
126
+ @keydown.ctrl.z.prevent="undo"
127
+ @keydown.ctrl.shift.z.prevent="redo"
128
+ >
129
+ <!-- keydown is more reliable for keyboard shortcuts -->
130
+ <!-- Add .prevent to stop browser default (e.g., save dialog) -->
131
+ </div>
132
+ </template>
133
+ ```
134
+
135
+ ## Reference
136
+ - [Vue.js Event Handling - Key Modifiers](https://vuejs.org/guide/essentials/event-handling.html#key-modifiers)
137
+ - [Vue.js Event Handling - System Modifier Keys](https://vuejs.org/guide/essentials/event-handling.html#system-modifier-keys)
@@ -0,0 +1,216 @@
1
+ ---
2
+ title: Access DOM Only After Mounted Hook
3
+ impact: HIGH
4
+ impactDescription: Accessing DOM elements before mounted causes undefined errors and silent failures
5
+ type: capability
6
+ tags: [vue3, vue2, lifecycle, dom, mounted, created, beforeMount, template-refs]
7
+ ---
8
+
9
+ # Access DOM Only After Mounted Hook
10
+
11
+ **Impact: HIGH** - Attempting to access DOM elements or `this.$el` in `created` or `beforeMount` hooks fails because the component's template has not yet been rendered to the DOM. This leads to undefined errors, null references, and failed third-party library initializations.
12
+
13
+ The component's DOM is only available starting from the `mounted` hook (Options API) or after `onMounted` runs (Composition API). Before this point, `this.$el` is undefined and template refs are null.
14
+
15
+ ## Task Checklist
16
+
17
+ - [ ] Perform DOM manipulations only in `mounted`/`onMounted` or later
18
+ - [ ] Initialize DOM-dependent libraries (charts, maps, editors) in mounted
19
+ - [ ] Use `created` for data initialization and API calls (non-DOM operations)
20
+ - [ ] Access template refs only after mounted
21
+ - [ ] Use `$nextTick` if you need DOM after reactive data changes
22
+
23
+ **Incorrect:**
24
+ ```javascript
25
+ // WRONG: Accessing DOM in created hook
26
+ export default {
27
+ created() {
28
+ // DOM doesn't exist yet!
29
+ console.log(this.$el) // undefined
30
+ this.$el.querySelector('.chart') // Error: Cannot read property 'querySelector' of undefined
31
+
32
+ // Third-party library initialization fails
33
+ new Chart(document.getElementById('myChart')) // Element doesn't exist yet
34
+ }
35
+ }
36
+ ```
37
+
38
+ ```javascript
39
+ // WRONG: Accessing DOM in beforeMount
40
+ export default {
41
+ beforeMount() {
42
+ // Still too early - template is compiled but not mounted
43
+ console.log(this.$el) // undefined in Vue 3
44
+ this.$refs.myInput.focus() // Error: Cannot read property 'focus' of undefined
45
+ }
46
+ }
47
+ ```
48
+
49
+ ```vue
50
+ <!-- WRONG: Accessing template ref synchronously in setup -->
51
+ <script setup>
52
+ import { ref } from 'vue'
53
+
54
+ const myInput = ref(null)
55
+
56
+ // This runs during setup, before mounting
57
+ myInput.value.focus() // Error: Cannot read property 'focus' of null
58
+ </script>
59
+
60
+ <template>
61
+ <input ref="myInput" />
62
+ </template>
63
+ ```
64
+
65
+ **Correct:**
66
+ ```javascript
67
+ // CORRECT: Use created for data, mounted for DOM
68
+ export default {
69
+ data() {
70
+ return { chartData: null }
71
+ },
72
+ async created() {
73
+ // Data fetching is fine in created
74
+ this.chartData = await fetchChartData()
75
+ },
76
+ mounted() {
77
+ // Now the DOM exists and is safe to access
78
+ console.log(this.$el) // <div>...</div>
79
+
80
+ // Initialize DOM-dependent libraries
81
+ this.chart = new Chart(this.$refs.chartCanvas, {
82
+ data: this.chartData
83
+ })
84
+ }
85
+ }
86
+ ```
87
+
88
+ ```vue
89
+ <!-- CORRECT: Access template refs in onMounted -->
90
+ <script setup>
91
+ import { ref, onMounted } from 'vue'
92
+
93
+ const myInput = ref(null)
94
+
95
+ onMounted(() => {
96
+ // DOM is now available
97
+ myInput.value.focus() // Works!
98
+ })
99
+ </script>
100
+
101
+ <template>
102
+ <input ref="myInput" />
103
+ </template>
104
+ ```
105
+
106
+ ```javascript
107
+ // CORRECT: Using $nextTick for DOM access after data changes
108
+ export default {
109
+ methods: {
110
+ async addItem() {
111
+ this.items.push(newItem)
112
+
113
+ // Wait for Vue to update the DOM
114
+ await this.$nextTick()
115
+
116
+ // Now the new element exists in DOM
117
+ this.$refs.list.lastElementChild.scrollIntoView()
118
+ }
119
+ }
120
+ }
121
+ ```
122
+
123
+ ## Vue 3 Composition API Pattern
124
+
125
+ ```vue
126
+ <script setup>
127
+ import { ref, onMounted, nextTick } from 'vue'
128
+
129
+ const listRef = ref(null)
130
+ const items = ref([])
131
+
132
+ onMounted(() => {
133
+ // Safe to access DOM here
134
+ listRef.value.style.height = '400px'
135
+ })
136
+ </script>
137
+ ```
138
+
139
+ ## Vue 3.5+ useTemplateRef Pattern
140
+
141
+ ```vue
142
+ <script setup>
143
+ import { useTemplateRef, onMounted } from 'vue'
144
+
145
+ // Vue 3.5+ recommended approach - decouples ref name from variable name
146
+ const input = useTemplateRef('my-input')
147
+
148
+ onMounted(() => {
149
+ input.value.focus()
150
+ })
151
+ </script>
152
+
153
+ <template>
154
+ <input ref="my-input" />
155
+ </template>
156
+ ```
157
+
158
+ ## Composition API with nextTick
159
+
160
+ ```vue
161
+ <script setup>
162
+ import { ref, nextTick } from 'vue'
163
+
164
+ const listRef = ref(null)
165
+ const items = ref([])
166
+
167
+ async function addItem(item) {
168
+ items.value.push(item)
169
+
170
+ // Wait for DOM update after reactive change
171
+ await nextTick()
172
+
173
+ // Now new item is in DOM
174
+ listRef.value.lastElementChild.focus()
175
+ }
176
+ </script>
177
+
178
+ <template>
179
+ <ul ref="listRef">
180
+ <li v-for="item in items" :key="item.id">{{ item.name }}</li>
181
+ </ul>
182
+ </template>
183
+ ```
184
+
185
+ ## Common Third-Party Libraries
186
+
187
+ ```javascript
188
+ // CORRECT: Initialize in mounted
189
+ export default {
190
+ mounted() {
191
+ // Chart.js
192
+ this.chart = new Chart(this.$refs.canvas, config)
193
+
194
+ // Leaflet maps
195
+ this.map = L.map(this.$refs.mapContainer).setView([51.505, -0.09], 13)
196
+
197
+ // Monaco Editor
198
+ this.editor = monaco.editor.create(this.$refs.editorContainer, options)
199
+
200
+ // Video.js
201
+ this.player = videojs(this.$refs.videoElement)
202
+ },
203
+ beforeUnmount() {
204
+ // Don't forget cleanup!
205
+ this.chart?.destroy()
206
+ this.map?.remove()
207
+ this.editor?.dispose()
208
+ this.player?.dispose()
209
+ }
210
+ }
211
+ ```
212
+
213
+ ## Reference
214
+ - [Vue.js Lifecycle Hooks](https://vuejs.org/guide/essentials/lifecycle.html)
215
+ - [Vue.js Template Refs](https://vuejs.org/guide/essentials/template-refs.html)
216
+ - [Vue.js nextTick](https://vuejs.org/api/general.html#nexttick)
@@ -0,0 +1,156 @@
1
+ ---
2
+ title: Register Lifecycle Hooks Synchronously During Setup
3
+ impact: HIGH
4
+ impactDescription: Asynchronously registered lifecycle hooks will never execute
5
+ type: capability
6
+ tags: [vue3, composition-api, lifecycle, onMounted, onUnmounted, async, setup]
7
+ ---
8
+
9
+ # Register Lifecycle Hooks Synchronously During Setup
10
+
11
+ **Impact: HIGH** - Lifecycle hooks registered asynchronously (e.g., inside setTimeout, after await) will never be called because Vue cannot associate them with the component instance. This leads to silent failures where expected initialization or cleanup code never runs.
12
+
13
+ In Vue 3's Composition API, lifecycle hooks like `onMounted`, `onUnmounted`, `onUpdated`, etc. must be registered synchronously during component setup. The hook registration doesn't need to be lexically inside `setup()` or `<script setup>`, but the call stack must be synchronous and originate from within setup.
14
+
15
+ ## Task Checklist
16
+
17
+ - [ ] Register all lifecycle hooks at the top level of setup() or `<script setup>`
18
+ - [ ] Never register hooks inside setTimeout, setInterval, or Promise callbacks
19
+ - [ ] When calling composables that use lifecycle hooks, call them synchronously
20
+ - [ ] Hooks CAN be in external functions if called synchronously from setup
21
+
22
+ **Incorrect:**
23
+ ```javascript
24
+ // WRONG: Hook registered asynchronously - will NEVER execute
25
+ import { onMounted } from 'vue'
26
+
27
+ export default {
28
+ async setup() {
29
+ // After await, we're in a different call stack
30
+ const data = await fetchInitialData()
31
+
32
+ // This hook will NOT be registered!
33
+ onMounted(() => {
34
+ console.log('This will never run')
35
+ })
36
+ }
37
+ }
38
+ ```
39
+
40
+ ```javascript
41
+ // WRONG: Hook registered in setTimeout - will NEVER execute
42
+ import { onMounted } from 'vue'
43
+
44
+ export default {
45
+ setup() {
46
+ setTimeout(() => {
47
+ // This is asynchronous - hook won't be registered!
48
+ onMounted(() => {
49
+ initializeChart()
50
+ })
51
+ }, 100)
52
+ }
53
+ }
54
+ ```
55
+
56
+ ```javascript
57
+ // WRONG: Hook registered in Promise callback
58
+ import { onMounted } from 'vue'
59
+
60
+ export default {
61
+ setup() {
62
+ fetchConfig().then(() => {
63
+ // Asynchronous! This will silently fail
64
+ onMounted(() => {
65
+ applyConfig()
66
+ })
67
+ })
68
+ }
69
+ }
70
+ ```
71
+
72
+ **Correct:**
73
+ ```javascript
74
+ // CORRECT: Hook registered synchronously at top level
75
+ import { onMounted, ref } from 'vue'
76
+
77
+ export default {
78
+ setup() {
79
+ const data = ref(null)
80
+
81
+ // Register hook synchronously FIRST
82
+ onMounted(async () => {
83
+ // Async operations are fine INSIDE the hook
84
+ data.value = await fetchInitialData()
85
+ initializeChart()
86
+ })
87
+
88
+ return { data }
89
+ }
90
+ }
91
+ ```
92
+
93
+ ```vue
94
+ <!-- CORRECT: <script setup> - hooks at top level -->
95
+ <script setup>
96
+ import { onMounted, onUnmounted, ref } from 'vue'
97
+
98
+ const isReady = ref(false)
99
+
100
+ // These are synchronous during script setup execution
101
+ onMounted(() => {
102
+ isReady.value = true
103
+ })
104
+
105
+ onUnmounted(() => {
106
+ cleanup()
107
+ })
108
+ </script>
109
+ ```
110
+
111
+ ```javascript
112
+ // CORRECT: Hook in external function called synchronously from setup
113
+ import { onMounted, onUnmounted } from 'vue'
114
+
115
+ function useWindowResize(callback) {
116
+ // This is fine - it's called synchronously from setup
117
+ onMounted(() => {
118
+ window.addEventListener('resize', callback)
119
+ })
120
+
121
+ onUnmounted(() => {
122
+ window.removeEventListener('resize', callback)
123
+ })
124
+ }
125
+
126
+ export default {
127
+ setup() {
128
+ // Composable called synchronously - hooks will be registered
129
+ useWindowResize(handleResize)
130
+ }
131
+ }
132
+ ```
133
+
134
+ ## Multiple Hooks Are Allowed
135
+
136
+ ```javascript
137
+ // CORRECT: You can register the same hook multiple times
138
+ import { onMounted } from 'vue'
139
+
140
+ export default {
141
+ setup() {
142
+ // Both will run, in order of registration
143
+ onMounted(() => {
144
+ initializeA()
145
+ })
146
+
147
+ onMounted(() => {
148
+ initializeB()
149
+ })
150
+ }
151
+ }
152
+ ```
153
+
154
+ ## Reference
155
+ - [Vue.js Lifecycle Hooks](https://vuejs.org/guide/essentials/lifecycle.html)
156
+ - [Composition API Lifecycle Hooks](https://vuejs.org/api/composition-api-lifecycle.html)