@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.
- package/README.md +63 -0
- package/index.mjs +139 -0
- package/package.json +34 -0
- package/skills/create-adaptable-composable/SKILL.md +76 -0
- package/skills/vue-best-practices/SKILL.md +154 -0
- package/skills/vue-best-practices/references/animation-class-based-technique.md +254 -0
- package/skills/vue-best-practices/references/animation-state-driven-technique.md +291 -0
- package/skills/vue-best-practices/references/component-async.md +97 -0
- package/skills/vue-best-practices/references/component-data-flow.md +350 -0
- package/skills/vue-best-practices/references/component-fallthrough-attrs.md +174 -0
- package/skills/vue-best-practices/references/component-keep-alive.md +137 -0
- package/skills/vue-best-practices/references/component-slots.md +216 -0
- package/skills/vue-best-practices/references/component-suspense.md +228 -0
- package/skills/vue-best-practices/references/component-teleport.md +108 -0
- package/skills/vue-best-practices/references/component-transition-group.md +128 -0
- package/skills/vue-best-practices/references/component-transition.md +125 -0
- package/skills/vue-best-practices/references/composables.md +290 -0
- package/skills/vue-best-practices/references/directives.md +162 -0
- package/skills/vue-best-practices/references/perf-avoid-component-abstraction-in-lists.md +159 -0
- package/skills/vue-best-practices/references/perf-v-once-v-memo-directives.md +182 -0
- package/skills/vue-best-practices/references/perf-virtualize-large-lists.md +187 -0
- package/skills/vue-best-practices/references/plugins.md +166 -0
- package/skills/vue-best-practices/references/reactivity.md +346 -0
- package/skills/vue-best-practices/references/render-functions.md +201 -0
- package/skills/vue-best-practices/references/sfc.md +310 -0
- package/skills/vue-best-practices/references/state-management.md +135 -0
- package/skills/vue-best-practices/references/updated-hook-performance.md +187 -0
- package/skills/vue-debug-guides/SKILL.md +205 -0
- package/skills/vue-debug-guides/reference/animation-key-for-rerender.md +160 -0
- package/skills/vue-debug-guides/reference/animation-transitiongroup-performance.md +241 -0
- package/skills/vue-debug-guides/reference/async-component-error-handling.md +115 -0
- package/skills/vue-debug-guides/reference/async-component-keepalive-ref-issue.md +112 -0
- package/skills/vue-debug-guides/reference/async-component-suspense-control.md +84 -0
- package/skills/vue-debug-guides/reference/async-component-vue-router.md +109 -0
- package/skills/vue-debug-guides/reference/attrs-event-listener-merging.md +205 -0
- package/skills/vue-debug-guides/reference/checkbox-true-false-value-form-submission.md +118 -0
- package/skills/vue-debug-guides/reference/cleanup-side-effects.md +172 -0
- package/skills/vue-debug-guides/reference/click-events-on-components.md +180 -0
- package/skills/vue-debug-guides/reference/component-naming-conflicts.md +159 -0
- package/skills/vue-debug-guides/reference/component-ref-requires-defineexpose.md +176 -0
- package/skills/vue-debug-guides/reference/composable-avoid-hidden-side-effects.md +208 -0
- package/skills/vue-debug-guides/reference/composable-call-location-restrictions.md +141 -0
- package/skills/vue-debug-guides/reference/composable-naming-return-pattern.md +139 -0
- package/skills/vue-debug-guides/reference/composable-tovalue-inside-watcheffect.md +182 -0
- package/skills/vue-debug-guides/reference/composition-api-not-functional-programming.md +120 -0
- package/skills/vue-debug-guides/reference/composition-api-script-setup-async-context.md +203 -0
- package/skills/vue-debug-guides/reference/composition-api-vs-react-hooks-differences.md +156 -0
- package/skills/vue-debug-guides/reference/computed-array-mutation.md +148 -0
- package/skills/vue-debug-guides/reference/computed-conditional-dependencies.md +147 -0
- package/skills/vue-debug-guides/reference/computed-no-parameters.md +159 -0
- package/skills/vue-debug-guides/reference/computed-no-side-effects.md +107 -0
- package/skills/vue-debug-guides/reference/computed-return-value-readonly.md +160 -0
- package/skills/vue-debug-guides/reference/configure-app-before-mount.md +89 -0
- package/skills/vue-debug-guides/reference/declare-emits-for-documentation.md +212 -0
- package/skills/vue-debug-guides/reference/define-expose-before-await.md +192 -0
- package/skills/vue-debug-guides/reference/define-model-default-value-sync.md +139 -0
- package/skills/vue-debug-guides/reference/defineEmits-must-be-top-level.md +164 -0
- package/skills/vue-debug-guides/reference/defineEmits-no-runtime-and-type-mixed.md +170 -0
- package/skills/vue-debug-guides/reference/definemodel-object-mutation-no-emit.md +148 -0
- package/skills/vue-debug-guides/reference/dom-update-timing-nexttick.md +90 -0
- package/skills/vue-debug-guides/reference/dynamic-argument-constraints.md +146 -0
- package/skills/vue-debug-guides/reference/dynamic-component-registration-vite.md +147 -0
- package/skills/vue-debug-guides/reference/event-modifier-order-matters.md +101 -0
- package/skills/vue-debug-guides/reference/exact-modifier-for-precise-shortcuts.md +155 -0
- package/skills/vue-debug-guides/reference/fallthrough-attrs-overwrite-vue3.md +159 -0
- package/skills/vue-debug-guides/reference/in-dom-template-parsing-caveats.md +149 -0
- package/skills/vue-debug-guides/reference/inheritattrs-false-for-wrapper-components.md +230 -0
- package/skills/vue-debug-guides/reference/keepalive-router-nested-double-mount.md +222 -0
- package/skills/vue-debug-guides/reference/keepalive-transition-memory-leak.md +144 -0
- package/skills/vue-debug-guides/reference/keyup-modifier-timing.md +137 -0
- package/skills/vue-debug-guides/reference/lifecycle-dom-access-timing.md +216 -0
- package/skills/vue-debug-guides/reference/lifecycle-hooks-synchronous-registration.md +156 -0
- package/skills/vue-debug-guides/reference/lifecycle-ssr-awareness.md +184 -0
- package/skills/vue-debug-guides/reference/local-components-not-in-descendants.md +151 -0
- package/skills/vue-debug-guides/reference/mount-return-value.md +88 -0
- package/skills/vue-debug-guides/reference/multi-root-component-class-attrs.md +93 -0
- package/skills/vue-debug-guides/reference/native-event-collision-with-emits.md +162 -0
- package/skills/vue-debug-guides/reference/no-passive-with-prevent.md +141 -0
- package/skills/vue-debug-guides/reference/no-v-if-with-v-for.md +136 -0
- package/skills/vue-debug-guides/reference/perf-computed-object-stability.md +157 -0
- package/skills/vue-debug-guides/reference/perf-props-stability-update-optimization.md +140 -0
- package/skills/vue-debug-guides/reference/plugin-global-properties-sparingly.md +109 -0
- package/skills/vue-debug-guides/reference/plugin-install-before-mount.md +124 -0
- package/skills/vue-debug-guides/reference/plugin-prefer-provide-inject-over-global-properties.md +120 -0
- package/skills/vue-debug-guides/reference/plugin-typescript-type-augmentation.md +157 -0
- package/skills/vue-debug-guides/reference/prop-defineprops-scope-limitation.md +161 -0
- package/skills/vue-debug-guides/reference/provide-inject-debugging-challenges.md +203 -0
- package/skills/vue-debug-guides/reference/provide-inject-default-value-factory.md +244 -0
- package/skills/vue-debug-guides/reference/provide-inject-reactivity-not-automatic.md +226 -0
- package/skills/vue-debug-guides/reference/provide-inject-synchronous-setup.md +235 -0
- package/skills/vue-debug-guides/reference/reactive-destructuring.md +89 -0
- package/skills/vue-debug-guides/reference/reactivity-debugging-hooks.md +132 -0
- package/skills/vue-debug-guides/reference/reactivity-markraw-for-non-reactive.md +149 -0
- package/skills/vue-debug-guides/reference/reactivity-proxy-identity-hazard.md +96 -0
- package/skills/vue-debug-guides/reference/reactivity-same-tick-batching.md +166 -0
- package/skills/vue-debug-guides/reference/ref-value-access.md +61 -0
- package/skills/vue-debug-guides/reference/refs-in-collections-need-value.md +81 -0
- package/skills/vue-debug-guides/reference/render-function-avoid-internal-vnode-properties.md +151 -0
- package/skills/vue-debug-guides/reference/render-function-vnodes-must-be-unique.md +133 -0
- package/skills/vue-debug-guides/reference/rendering-render-function-h-import-vue3.md +148 -0
- package/skills/vue-debug-guides/reference/rendering-render-function-return-from-setup.md +148 -0
- package/skills/vue-debug-guides/reference/rendering-render-function-slots-as-functions.md +168 -0
- package/skills/vue-debug-guides/reference/rendering-resolve-component-for-string-names.md +231 -0
- package/skills/vue-debug-guides/reference/select-initial-value-ios-bug.md +91 -0
- package/skills/vue-debug-guides/reference/self-referencing-component-name.md +157 -0
- package/skills/vue-debug-guides/reference/sfc-named-exports-forbidden.md +184 -0
- package/skills/vue-debug-guides/reference/sfc-scoped-css-child-component-styling.md +156 -0
- package/skills/vue-debug-guides/reference/sfc-scoped-css-dynamic-content.md +193 -0
- package/skills/vue-debug-guides/reference/sfc-scoped-css-slot-content.md +242 -0
- package/skills/vue-debug-guides/reference/sfc-script-setup-reactivity.md +195 -0
- package/skills/vue-debug-guides/reference/slot-forwarding-to-child-components.md +143 -0
- package/skills/vue-debug-guides/reference/slot-implicit-default-content.md +155 -0
- package/skills/vue-debug-guides/reference/slot-name-reserved-prop.md +109 -0
- package/skills/vue-debug-guides/reference/slot-named-scoped-explicit-default.md +95 -0
- package/skills/vue-debug-guides/reference/slot-render-scope-parent-only.md +135 -0
- package/skills/vue-debug-guides/reference/slot-v-slot-on-components-or-templates-only.md +122 -0
- package/skills/vue-debug-guides/reference/ssr-hydration-mismatch-causes.md +280 -0
- package/skills/vue-debug-guides/reference/ssr-platform-specific-apis.md +256 -0
- package/skills/vue-debug-guides/reference/state-ssr-cross-request-pollution.md +276 -0
- package/skills/vue-debug-guides/reference/suspense-no-builtin-error-handling.md +127 -0
- package/skills/vue-debug-guides/reference/suspense-ssr-hydration-issues.md +159 -0
- package/skills/vue-debug-guides/reference/tailwind-dynamic-class-generation.md +144 -0
- package/skills/vue-debug-guides/reference/teleport-scoped-styles-limitation.md +191 -0
- package/skills/vue-debug-guides/reference/teleport-ssr-hydration.md +152 -0
- package/skills/vue-debug-guides/reference/teleport-target-must-exist.md +113 -0
- package/skills/vue-debug-guides/reference/template-expressions-restrictions.md +114 -0
- package/skills/vue-debug-guides/reference/template-functions-no-side-effects.md +187 -0
- package/skills/vue-debug-guides/reference/template-ref-null-with-v-if.md +123 -0
- package/skills/vue-debug-guides/reference/template-ref-unwrapping-top-level.md +104 -0
- package/skills/vue-debug-guides/reference/template-ref-v-for-order.md +172 -0
- package/skills/vue-debug-guides/reference/textarea-no-interpolation.md +72 -0
- package/skills/vue-debug-guides/reference/transition-group-flip-inline-elements.md +152 -0
- package/skills/vue-debug-guides/reference/transition-group-move-animation-position-absolute.md +130 -0
- package/skills/vue-debug-guides/reference/transition-group-no-default-wrapper-vue3.md +152 -0
- package/skills/vue-debug-guides/reference/transition-js-hooks-done-callback.md +251 -0
- package/skills/vue-debug-guides/reference/transition-nested-duration.md +182 -0
- package/skills/vue-debug-guides/reference/transition-reusable-scoped-style.md +245 -0
- package/skills/vue-debug-guides/reference/transition-router-view-appear.md +193 -0
- package/skills/vue-debug-guides/reference/transition-type-when-mixed.md +172 -0
- package/skills/vue-debug-guides/reference/transition-unmount-hook-timing.md +149 -0
- package/skills/vue-debug-guides/reference/ts-defineprops-boolean-default-false.md +225 -0
- package/skills/vue-debug-guides/reference/ts-defineprops-imported-types-limitations.md +281 -0
- package/skills/vue-debug-guides/reference/ts-event-handler-explicit-typing.md +213 -0
- package/skills/vue-debug-guides/reference/ts-reactive-no-generic-argument.md +196 -0
- package/skills/vue-debug-guides/reference/ts-shallowref-for-dynamic-components.md +218 -0
- package/skills/vue-debug-guides/reference/ts-template-ref-null-handling.md +249 -0
- package/skills/vue-debug-guides/reference/ts-template-type-casting.md +214 -0
- package/skills/vue-debug-guides/reference/ts-withdefaults-mutable-factory-function.md +171 -0
- package/skills/vue-debug-guides/reference/undeclared-emits-double-firing.md +195 -0
- package/skills/vue-debug-guides/reference/use-template-ref-vue35.md +158 -0
- package/skills/vue-debug-guides/reference/v-else-must-follow-v-if.md +136 -0
- package/skills/vue-debug-guides/reference/v-for-component-props.md +95 -0
- package/skills/vue-debug-guides/reference/v-for-computed-reverse-sort.md +86 -0
- package/skills/vue-debug-guides/reference/v-for-key-attribute.md +90 -0
- package/skills/vue-debug-guides/reference/v-for-range-starts-at-one.md +66 -0
- package/skills/vue-debug-guides/reference/v-if-null-check-order.md +171 -0
- package/skills/vue-debug-guides/reference/v-model-ignores-html-attributes.md +83 -0
- package/skills/vue-debug-guides/reference/v-model-ime-composition.md +83 -0
- package/skills/vue-debug-guides/reference/v-model-number-modifier-behavior.md +124 -0
- package/skills/vue-debug-guides/reference/v-show-template-limitation.md +124 -0
- package/skills/vue-debug-guides/reference/watch-async-cleanup.md +180 -0
- package/skills/vue-debug-guides/reference/watch-async-creation-memory-leak.md +176 -0
- package/skills/vue-debug-guides/reference/watch-deep-same-object-reference.md +165 -0
- package/skills/vue-debug-guides/reference/watch-flush-timing.md +189 -0
- package/skills/vue-debug-guides/reference/watch-reactive-property-getter.md +108 -0
- package/skills/vue-debug-guides/reference/watcheffect-async-dependency-tracking.md +173 -0
- package/skills/vue-debug-guides/reference/watcheffect-flush-post-for-refs.md +176 -0
- package/skills/vue-jsx-best-practices/SKILL.md +12 -0
- package/skills/vue-jsx-best-practices/reference/render-function-jsx-vue-vs-react.md +141 -0
- package/skills/vue-options-api-best-practices/SKILL.md +23 -0
- package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-lifecycle-hooks.md +95 -0
- package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-methods.md +68 -0
- package/skills/vue-options-api-best-practices/reference/stateful-methods-lifecycle.md +61 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-arrow-functions-validators.md +141 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-computed-return-types.md +192 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-proptype-complex-types.md +212 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-provide-inject-limitations.md +135 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-type-event-handlers.md +202 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-use-definecomponent.md +172 -0
- package/skills/vue-options-api-best-practices/reference/ts-strict-mode-options-api.md +197 -0
- package/skills/vue-pinia-best-practices/SKILL.md +21 -0
- package/skills/vue-pinia-best-practices/reference/pinia-no-active-pinia-error.md +248 -0
- package/skills/vue-pinia-best-practices/reference/pinia-setup-store-return-all-state.md +227 -0
- package/skills/vue-pinia-best-practices/reference/pinia-store-destructuring-breaks-reactivity.md +193 -0
- package/skills/vue-pinia-best-practices/reference/state-url-for-ephemeral-filters.md +238 -0
- package/skills/vue-pinia-best-practices/reference/state-use-pinia-for-large-apps.md +262 -0
- package/skills/vue-pinia-best-practices/reference/store-method-binding-parentheses.md +191 -0
- package/skills/vue-router-best-practices/SKILL.md +23 -0
- package/skills/vue-router-best-practices/reference/router-beforeenter-no-param-trigger.md +167 -0
- package/skills/vue-router-best-practices/reference/router-beforerouteenter-no-this.md +176 -0
- package/skills/vue-router-best-practices/reference/router-guard-async-await-pattern.md +227 -0
- package/skills/vue-router-best-practices/reference/router-navigation-guard-infinite-loop.md +187 -0
- package/skills/vue-router-best-practices/reference/router-navigation-guard-next-deprecated.md +150 -0
- package/skills/vue-router-best-practices/reference/router-param-change-no-lifecycle.md +181 -0
- package/skills/vue-router-best-practices/reference/router-simple-routing-cleanup.md +209 -0
- package/skills/vue-router-best-practices/reference/router-use-vue-router-for-production.md +183 -0
- package/skills/vue-testing-best-practices/SKILL.md +29 -0
- package/skills/vue-testing-best-practices/reference/async-component-testing.md +163 -0
- package/skills/vue-testing-best-practices/reference/teleport-testing-complexity.md +158 -0
- package/skills/vue-testing-best-practices/reference/testing-async-await-flushpromises.md +175 -0
- package/skills/vue-testing-best-practices/reference/testing-browser-vs-node-runners.md +208 -0
- package/skills/vue-testing-best-practices/reference/testing-component-blackbox-approach.md +144 -0
- package/skills/vue-testing-best-practices/reference/testing-composables-helper-wrapper.md +238 -0
- package/skills/vue-testing-best-practices/reference/testing-e2e-playwright-recommended.md +242 -0
- package/skills/vue-testing-best-practices/reference/testing-no-snapshot-only.md +197 -0
- package/skills/vue-testing-best-practices/reference/testing-pinia-store-setup.md +228 -0
- package/skills/vue-testing-best-practices/reference/testing-suspense-async-components.md +229 -0
- package/skills/vue-testing-best-practices/reference/testing-vitest-recommended-for-vue.md +204 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Scoped Styles May Not Apply to Teleported Content
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: Scoped styles can fail to apply to teleported elements due to data attribute limitations
|
|
5
|
+
type: gotcha
|
|
6
|
+
tags: [vue3, teleport, scoped-styles, css]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Scoped Styles May Not Apply to Teleported Content
|
|
10
|
+
|
|
11
|
+
**Impact: MEDIUM** - When using scoped styles with Teleport, the styles may not apply correctly to teleported elements. This is a known limitation related to how Vue's scoped style attributes work with elements rendered outside the component's DOM tree.
|
|
12
|
+
|
|
13
|
+
## Task Checklist
|
|
14
|
+
|
|
15
|
+
- [ ] Test scoped styles on teleported content
|
|
16
|
+
- [ ] Use `:deep()` selector or non-scoped styles for teleported content
|
|
17
|
+
- [ ] Consider CSS modules as an alternative
|
|
18
|
+
- [ ] Keep teleported content styles in a separate non-scoped style block
|
|
19
|
+
|
|
20
|
+
**Problem - Scoped Styles Not Applied:**
|
|
21
|
+
```vue
|
|
22
|
+
<template>
|
|
23
|
+
<Teleport to="body">
|
|
24
|
+
<div class="modal">
|
|
25
|
+
<p class="modal-text">This text may not be styled!</p>
|
|
26
|
+
</div>
|
|
27
|
+
</Teleport>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<style scoped>
|
|
31
|
+
/* These styles may NOT apply to teleported content */
|
|
32
|
+
.modal {
|
|
33
|
+
background: white;
|
|
34
|
+
padding: 20px;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.modal-text {
|
|
38
|
+
color: blue; /* May not work */
|
|
39
|
+
}
|
|
40
|
+
</style>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Solution 1 - Use Non-Scoped Styles for Teleported Content:**
|
|
44
|
+
```vue
|
|
45
|
+
<template>
|
|
46
|
+
<Teleport to="body">
|
|
47
|
+
<div class="my-modal">
|
|
48
|
+
<p class="my-modal-text">This text will be styled</p>
|
|
49
|
+
</div>
|
|
50
|
+
</Teleport>
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<style scoped>
|
|
54
|
+
/* Component-specific styles */
|
|
55
|
+
.button { color: blue; }
|
|
56
|
+
</style>
|
|
57
|
+
|
|
58
|
+
<style>
|
|
59
|
+
/* Non-scoped styles for teleported content */
|
|
60
|
+
/* Use specific class names to avoid conflicts */
|
|
61
|
+
.my-modal {
|
|
62
|
+
background: white;
|
|
63
|
+
padding: 20px;
|
|
64
|
+
position: fixed;
|
|
65
|
+
top: 50%;
|
|
66
|
+
left: 50%;
|
|
67
|
+
transform: translate(-50%, -50%);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.my-modal-text {
|
|
71
|
+
color: blue;
|
|
72
|
+
}
|
|
73
|
+
</style>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Solution 2 - Use :deep() Selector:**
|
|
77
|
+
```vue
|
|
78
|
+
<template>
|
|
79
|
+
<Teleport to="body">
|
|
80
|
+
<div class="modal">
|
|
81
|
+
<p class="modal-text">Styled with :deep()</p>
|
|
82
|
+
</div>
|
|
83
|
+
</Teleport>
|
|
84
|
+
</template>
|
|
85
|
+
|
|
86
|
+
<style scoped>
|
|
87
|
+
:deep(.modal) {
|
|
88
|
+
background: white;
|
|
89
|
+
padding: 20px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
:deep(.modal-text) {
|
|
93
|
+
color: blue;
|
|
94
|
+
}
|
|
95
|
+
</style>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Solution 3 - CSS Modules:**
|
|
99
|
+
```vue
|
|
100
|
+
<template>
|
|
101
|
+
<Teleport to="body">
|
|
102
|
+
<div :class="$style.modal">
|
|
103
|
+
<p :class="$style.modalText">Styled with CSS modules</p>
|
|
104
|
+
</div>
|
|
105
|
+
</Teleport>
|
|
106
|
+
</template>
|
|
107
|
+
|
|
108
|
+
<style module>
|
|
109
|
+
.modal {
|
|
110
|
+
background: white;
|
|
111
|
+
padding: 20px;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.modalText {
|
|
115
|
+
color: blue;
|
|
116
|
+
}
|
|
117
|
+
</style>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Multi-Root Components with Teleport
|
|
121
|
+
|
|
122
|
+
Using Teleport as one of multiple root nodes causes additional issues:
|
|
123
|
+
|
|
124
|
+
```vue
|
|
125
|
+
<template>
|
|
126
|
+
<!-- Multi-root component -->
|
|
127
|
+
<button @click="open = true">Open</button>
|
|
128
|
+
<Teleport to="body">
|
|
129
|
+
<div class="modal">Content</div>
|
|
130
|
+
</Teleport>
|
|
131
|
+
</template>
|
|
132
|
+
|
|
133
|
+
<!-- Warning: class/style attributes may not be inherited -->
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Pass classes explicitly to avoid inheritance issues:
|
|
137
|
+
|
|
138
|
+
```vue
|
|
139
|
+
<template>
|
|
140
|
+
<button @click="open = true">Open</button>
|
|
141
|
+
<Teleport to="body">
|
|
142
|
+
<div :class="['modal', $attrs.class]" :style="$attrs.style">
|
|
143
|
+
Content
|
|
144
|
+
</div>
|
|
145
|
+
</Teleport>
|
|
146
|
+
</template>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Best Practice: Dedicated Modal Styles
|
|
150
|
+
|
|
151
|
+
Create a dedicated stylesheet for modal/overlay components:
|
|
152
|
+
|
|
153
|
+
```css
|
|
154
|
+
/* modal-styles.css */
|
|
155
|
+
.modal-overlay {
|
|
156
|
+
position: fixed;
|
|
157
|
+
inset: 0;
|
|
158
|
+
background: rgba(0, 0, 0, 0.5);
|
|
159
|
+
display: flex;
|
|
160
|
+
align-items: center;
|
|
161
|
+
justify-content: center;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.modal-content {
|
|
165
|
+
background: white;
|
|
166
|
+
border-radius: 8px;
|
|
167
|
+
padding: 24px;
|
|
168
|
+
max-width: 500px;
|
|
169
|
+
width: 90%;
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
```vue
|
|
174
|
+
<script setup>
|
|
175
|
+
import './modal-styles.css'
|
|
176
|
+
</script>
|
|
177
|
+
|
|
178
|
+
<template>
|
|
179
|
+
<Teleport to="body">
|
|
180
|
+
<div v-if="open" class="modal-overlay">
|
|
181
|
+
<div class="modal-content">
|
|
182
|
+
<slot />
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
</Teleport>
|
|
186
|
+
</template>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Reference
|
|
190
|
+
- [Vue.js SFC CSS Features - Scoped CSS](https://vuejs.org/api/sfc-css-features.html#scoped-css)
|
|
191
|
+
- [GitHub Issue #2047 - Scoped styles and teleport](https://github.com/vuejs/core/issues/2047)
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Handle Teleport SSR Hydration Carefully
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: Teleported content causes hydration mismatches in SSR/SSG applications
|
|
5
|
+
type: gotcha
|
|
6
|
+
tags: [vue3, teleport, ssr, nuxt, hydration]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Handle Teleport SSR Hydration Carefully
|
|
10
|
+
|
|
11
|
+
**Impact: HIGH** - Teleports require special handling during SSR. The teleported content is not part of the server-rendered HTML string, causing hydration mismatches that can break the application or cause content to disappear.
|
|
12
|
+
|
|
13
|
+
This is a critical issue for Nuxt, Quasar SSR, and custom Vue SSR setups.
|
|
14
|
+
|
|
15
|
+
## Task Checklist
|
|
16
|
+
|
|
17
|
+
- [ ] Wrap Teleport in `<ClientOnly>` component (Nuxt) for client-only rendering
|
|
18
|
+
- [ ] Use conditional rendering based on mount state for non-Nuxt SSR
|
|
19
|
+
- [ ] Use `data-allow-mismatch` attribute in Vue 3.5+ when intentional
|
|
20
|
+
- [ ] Test SSR applications thoroughly for hydration issues
|
|
21
|
+
|
|
22
|
+
**Problem - SSR Hydration Mismatch:**
|
|
23
|
+
```vue
|
|
24
|
+
<template>
|
|
25
|
+
<!-- Server renders nothing for teleported content -->
|
|
26
|
+
<!-- Client expects teleported content at #modals -->
|
|
27
|
+
<!-- = Hydration mismatch -->
|
|
28
|
+
<Teleport to="#modals">
|
|
29
|
+
<div v-if="showModal" class="modal">
|
|
30
|
+
Modal content
|
|
31
|
+
</div>
|
|
32
|
+
</Teleport>
|
|
33
|
+
</template>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Common error messages:
|
|
37
|
+
```
|
|
38
|
+
[Vue warn]: Hydration children mismatch in <div>:
|
|
39
|
+
server rendered element contains fewer child nodes than client vdom.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Solution 1 - Nuxt ClientOnly:**
|
|
43
|
+
```vue
|
|
44
|
+
<template>
|
|
45
|
+
<button @click="showModal = true">Open Modal</button>
|
|
46
|
+
|
|
47
|
+
<!-- Only render on client, avoiding SSR -->
|
|
48
|
+
<ClientOnly>
|
|
49
|
+
<Teleport to="body">
|
|
50
|
+
<div v-if="showModal" class="modal">
|
|
51
|
+
Modal content
|
|
52
|
+
</div>
|
|
53
|
+
</Teleport>
|
|
54
|
+
</ClientOnly>
|
|
55
|
+
</template>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Solution 2 - Manual Client Detection:**
|
|
59
|
+
```vue
|
|
60
|
+
<template>
|
|
61
|
+
<button @click="showModal = true">Open Modal</button>
|
|
62
|
+
|
|
63
|
+
<!-- Only render after component mounts on client -->
|
|
64
|
+
<Teleport v-if="isMounted" to="body">
|
|
65
|
+
<div v-if="showModal" class="modal">
|
|
66
|
+
Modal content
|
|
67
|
+
</div>
|
|
68
|
+
</Teleport>
|
|
69
|
+
</template>
|
|
70
|
+
|
|
71
|
+
<script setup>
|
|
72
|
+
import { ref, onMounted } from 'vue'
|
|
73
|
+
|
|
74
|
+
const showModal = ref(false)
|
|
75
|
+
const isMounted = ref(false)
|
|
76
|
+
|
|
77
|
+
onMounted(() => {
|
|
78
|
+
isMounted.value = true
|
|
79
|
+
})
|
|
80
|
+
</script>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Solution 3 - Vue 3.5+ data-allow-mismatch:**
|
|
84
|
+
```vue
|
|
85
|
+
<template>
|
|
86
|
+
<!-- Suppress hydration warnings for intentional mismatches -->
|
|
87
|
+
<div data-allow-mismatch>
|
|
88
|
+
<Teleport to="body">
|
|
89
|
+
<div v-if="showModal" class="modal">
|
|
90
|
+
Modal content
|
|
91
|
+
</div>
|
|
92
|
+
</Teleport>
|
|
93
|
+
</div>
|
|
94
|
+
</template>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## SSR with Multiple Teleports
|
|
98
|
+
|
|
99
|
+
Multiple teleports to the same target can cause additional hydration issues:
|
|
100
|
+
|
|
101
|
+
```vue
|
|
102
|
+
<!-- Parent.vue -->
|
|
103
|
+
<template>
|
|
104
|
+
<!-- First teleport -->
|
|
105
|
+
<Teleport to="#modals">
|
|
106
|
+
<NotificationBanner />
|
|
107
|
+
</Teleport>
|
|
108
|
+
|
|
109
|
+
<ChildComponent />
|
|
110
|
+
</template>
|
|
111
|
+
|
|
112
|
+
<!-- ChildComponent.vue -->
|
|
113
|
+
<template>
|
|
114
|
+
<!-- Second teleport to same target - order matters! -->
|
|
115
|
+
<Teleport to="#modals">
|
|
116
|
+
<Modal />
|
|
117
|
+
</Teleport>
|
|
118
|
+
</template>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
For SSR, ensure consistent ordering or wrap each in `ClientOnly`.
|
|
122
|
+
|
|
123
|
+
## Element Plus and UI Library SSR
|
|
124
|
+
|
|
125
|
+
Many UI libraries use Teleport internally. Element Plus components that use Teleport include:
|
|
126
|
+
- ElDialog
|
|
127
|
+
- ElDrawer
|
|
128
|
+
- ElTooltip
|
|
129
|
+
- ElDropdown
|
|
130
|
+
- ElSelect
|
|
131
|
+
- ElDatePicker
|
|
132
|
+
|
|
133
|
+
```vue
|
|
134
|
+
<template>
|
|
135
|
+
<!-- These need special SSR handling -->
|
|
136
|
+
<ClientOnly>
|
|
137
|
+
<ElDialog v-model="visible">
|
|
138
|
+
Dialog content
|
|
139
|
+
</ElDialog>
|
|
140
|
+
</ClientOnly>
|
|
141
|
+
</template>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Known Vue Issues
|
|
145
|
+
|
|
146
|
+
- Disabled teleports in fragments can cause hydration mismatches (Vue issue #6152)
|
|
147
|
+
- Nested teleports may cause app to break on hydration (Vue issue #5242)
|
|
148
|
+
|
|
149
|
+
## Reference
|
|
150
|
+
- [Vue.js SSR - Teleports](https://vuejs.org/guide/scaling-up/ssr.html#teleports)
|
|
151
|
+
- [Element Plus SSR Guide](https://element-plus.org/en-US/guide/ssr.html)
|
|
152
|
+
- [Nuxt ClientOnly Component](https://nuxt.com/docs/api/components/client-only)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Teleport Target Must Exist Before Mount
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: Teleport will fail silently or throw errors if target element doesn't exist when component mounts
|
|
5
|
+
type: gotcha
|
|
6
|
+
tags: [vue3, teleport, modal, dom, lifecycle]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Teleport Target Must Exist Before Mount
|
|
10
|
+
|
|
11
|
+
**Impact: HIGH** - The teleport `to` target must already exist in the DOM when the `<Teleport>` component is mounted. If the target doesn't exist, Vue will throw an error and the teleported content won't render.
|
|
12
|
+
|
|
13
|
+
This is a common source of bugs when using modals, tooltips, or other teleported UI elements, especially when targeting Vue-rendered elements.
|
|
14
|
+
|
|
15
|
+
## Task Checklist
|
|
16
|
+
|
|
17
|
+
- [ ] Ensure teleport target exists in the DOM before `<Teleport>` mounts
|
|
18
|
+
- [ ] Place teleport containers (e.g., `#modals`, `#tooltips`) in `index.html` outside the Vue app
|
|
19
|
+
- [ ] If targeting Vue-rendered elements, ensure they mount before the Teleport
|
|
20
|
+
- [ ] Use Vue 3.5+ `defer` prop when target is rendered later in the same component tree
|
|
21
|
+
|
|
22
|
+
**Incorrect:**
|
|
23
|
+
```vue
|
|
24
|
+
<template>
|
|
25
|
+
<!-- ERROR: Target doesn't exist yet when Teleport mounts -->
|
|
26
|
+
<Teleport to="#modal-container">
|
|
27
|
+
<div class="modal">Modal content</div>
|
|
28
|
+
</Teleport>
|
|
29
|
+
|
|
30
|
+
<!-- Target is defined after the Teleport -->
|
|
31
|
+
<div id="modal-container"></div>
|
|
32
|
+
</template>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Correct - Option 1: External container in index.html:**
|
|
36
|
+
```html
|
|
37
|
+
<!-- index.html -->
|
|
38
|
+
<body>
|
|
39
|
+
<div id="app"></div>
|
|
40
|
+
<!-- Container exists before Vue app mounts -->
|
|
41
|
+
<div id="modals"></div>
|
|
42
|
+
<div id="tooltips"></div>
|
|
43
|
+
</body>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```vue
|
|
47
|
+
<template>
|
|
48
|
+
<!-- Safe: #modals exists before any Vue component mounts -->
|
|
49
|
+
<Teleport to="#modals">
|
|
50
|
+
<div v-if="showModal" class="modal">Modal content</div>
|
|
51
|
+
</Teleport>
|
|
52
|
+
</template>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Correct - Option 2: Teleport to body:**
|
|
56
|
+
```vue
|
|
57
|
+
<template>
|
|
58
|
+
<!-- Safe: body always exists -->
|
|
59
|
+
<Teleport to="body">
|
|
60
|
+
<div v-if="showModal" class="modal">Modal content</div>
|
|
61
|
+
</Teleport>
|
|
62
|
+
</template>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Correct - Option 3: Vue 3.5+ defer prop:**
|
|
66
|
+
```vue
|
|
67
|
+
<template>
|
|
68
|
+
<!-- Works in Vue 3.5+: defer resolves target after other parts mount -->
|
|
69
|
+
<Teleport defer to="#late-container">
|
|
70
|
+
<div class="modal">Modal content</div>
|
|
71
|
+
</Teleport>
|
|
72
|
+
|
|
73
|
+
<!-- Target rendered later in template -->
|
|
74
|
+
<div id="late-container"></div>
|
|
75
|
+
</template>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Defer Prop Limitations (Vue 3.5+)
|
|
79
|
+
|
|
80
|
+
The `defer` prop only waits for elements rendered in the **same mount/update tick**:
|
|
81
|
+
|
|
82
|
+
```vue
|
|
83
|
+
<template>
|
|
84
|
+
<!-- ERROR: defer won't help if target mounts asynchronously -->
|
|
85
|
+
<Teleport defer to="#async-container">
|
|
86
|
+
<div>Content</div>
|
|
87
|
+
</Teleport>
|
|
88
|
+
|
|
89
|
+
<!-- If this component loads asynchronously, defer won't work -->
|
|
90
|
+
<Suspense>
|
|
91
|
+
<AsyncComponent /> <!-- Contains #async-container -->
|
|
92
|
+
</Suspense>
|
|
93
|
+
</template>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Common Patterns
|
|
97
|
+
|
|
98
|
+
### Recommended: Centralized Teleport Containers
|
|
99
|
+
```html
|
|
100
|
+
<!-- index.html -->
|
|
101
|
+
<body>
|
|
102
|
+
<div id="app"></div>
|
|
103
|
+
|
|
104
|
+
<!-- Teleport destinations outside Vue app -->
|
|
105
|
+
<div id="modals" aria-live="polite"></div>
|
|
106
|
+
<div id="notifications" aria-live="assertive"></div>
|
|
107
|
+
<div id="tooltips"></div>
|
|
108
|
+
</body>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Reference
|
|
112
|
+
- [Vue.js Teleport - Using with Vue-rendered Targets](https://vuejs.org/guide/built-ins/teleport.html#using-with-vue-rendered-targets)
|
|
113
|
+
- [Vue.js Teleport - Deferred Teleport](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Template Expressions Must Be Single Expressions
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: Using statements instead of expressions in templates causes compilation errors
|
|
5
|
+
type: capability
|
|
6
|
+
tags: [vue3, template, expressions, interpolation, syntax]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Template Expressions Must Be Single Expressions
|
|
10
|
+
|
|
11
|
+
**Impact: MEDIUM** - Vue templates only support single JavaScript expressions, not statements. Using variable declarations, if statements, or multiple statements will cause template compilation errors.
|
|
12
|
+
|
|
13
|
+
Template interpolation `{{ }}` and directive bindings evaluate JavaScript expressions that produce a value. Statements like `if`, `for`, variable declarations, or multi-line code blocks are not allowed.
|
|
14
|
+
|
|
15
|
+
## Task Checklist
|
|
16
|
+
|
|
17
|
+
- [ ] Use only single expressions in `{{ }}` interpolation
|
|
18
|
+
- [ ] Use ternary operators instead of if/else statements
|
|
19
|
+
- [ ] Move complex logic to computed properties or methods
|
|
20
|
+
- [ ] Avoid variable declarations in templates
|
|
21
|
+
- [ ] Use `v-if`/`v-else` directives for conditional rendering
|
|
22
|
+
|
|
23
|
+
**Incorrect:**
|
|
24
|
+
```vue
|
|
25
|
+
<template>
|
|
26
|
+
<!-- ERROR: Variable declaration is a statement, not expression -->
|
|
27
|
+
<p>{{ var greeting = 'Hello' }}</p>
|
|
28
|
+
<p>{{ let x = 1 }}</p>
|
|
29
|
+
<p>{{ const name = 'Vue' }}</p>
|
|
30
|
+
|
|
31
|
+
<!-- ERROR: if statement not allowed -->
|
|
32
|
+
<p>{{ if (ok) { return message } }}</p>
|
|
33
|
+
<p>{{ if (user) return user.name }}</p>
|
|
34
|
+
|
|
35
|
+
<!-- ERROR: Multiple statements not allowed -->
|
|
36
|
+
<p>{{ count++; return count }}</p>
|
|
37
|
+
<p>{{ items.push(newItem); items.length }}</p>
|
|
38
|
+
|
|
39
|
+
<!-- ERROR: for/while loops not allowed -->
|
|
40
|
+
<p>{{ for (let i = 0; i < 5; i++) { } }}</p>
|
|
41
|
+
</template>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Correct:**
|
|
45
|
+
```vue
|
|
46
|
+
<template>
|
|
47
|
+
<!-- OK: Simple expressions -->
|
|
48
|
+
<p>{{ message }}</p>
|
|
49
|
+
<p>{{ count + 1 }}</p>
|
|
50
|
+
<p>{{ items.length }}</p>
|
|
51
|
+
|
|
52
|
+
<!-- OK: Ternary operators for conditionals -->
|
|
53
|
+
<p>{{ ok ? 'YES' : 'NO' }}</p>
|
|
54
|
+
<p>{{ user ? user.name : 'Guest' }}</p>
|
|
55
|
+
<p>{{ score >= 60 ? 'Pass' : 'Fail' }}</p>
|
|
56
|
+
|
|
57
|
+
<!-- OK: Method/function calls -->
|
|
58
|
+
<p>{{ formatDate(date) }}</p>
|
|
59
|
+
<p>{{ items.filter(i => i.active).length }}</p>
|
|
60
|
+
|
|
61
|
+
<!-- OK: Chained expressions -->
|
|
62
|
+
<p>{{ message.split('').reverse().join('') }}</p>
|
|
63
|
+
|
|
64
|
+
<!-- OK: Template literals -->
|
|
65
|
+
<p>{{ `Hello, ${name}!` }}</p>
|
|
66
|
+
|
|
67
|
+
<!-- OK: Object/array expressions -->
|
|
68
|
+
<p>{{ { name: 'Vue', version: 3 } }}</p>
|
|
69
|
+
</template>
|
|
70
|
+
|
|
71
|
+
<script setup>
|
|
72
|
+
import { ref, computed } from 'vue'
|
|
73
|
+
|
|
74
|
+
const ok = ref(true)
|
|
75
|
+
const message = ref('Hello')
|
|
76
|
+
const user = ref({ name: 'Alice' })
|
|
77
|
+
const score = ref(85)
|
|
78
|
+
|
|
79
|
+
// Move complex logic to computed properties
|
|
80
|
+
const greeting = computed(() => {
|
|
81
|
+
if (user.value) {
|
|
82
|
+
return `Welcome back, ${user.value.name}!`
|
|
83
|
+
}
|
|
84
|
+
return 'Hello, Guest!'
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
// Or use methods for reusable logic
|
|
88
|
+
function formatDate(date) {
|
|
89
|
+
return new Date(date).toLocaleDateString()
|
|
90
|
+
}
|
|
91
|
+
</script>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Use Directives for Control Flow
|
|
95
|
+
|
|
96
|
+
```vue
|
|
97
|
+
<template>
|
|
98
|
+
<!-- Instead of if/else in expressions, use v-if/v-else -->
|
|
99
|
+
<p v-if="user">Welcome, {{ user.name }}!</p>
|
|
100
|
+
<p v-else>Please log in</p>
|
|
101
|
+
|
|
102
|
+
<!-- Instead of loops in expressions, use v-for -->
|
|
103
|
+
<ul>
|
|
104
|
+
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
|
|
105
|
+
</ul>
|
|
106
|
+
|
|
107
|
+
<!-- Conditional display without removing from DOM -->
|
|
108
|
+
<p v-show="isVisible">This toggles visibility</p>
|
|
109
|
+
</template>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Reference
|
|
113
|
+
- [Vue.js Template Syntax - Using JavaScript Expressions](https://vuejs.org/guide/essentials/template-syntax.html#using-javascript-expressions)
|
|
114
|
+
- [Vue.js Conditional Rendering](https://vuejs.org/guide/essentials/conditional.html)
|