devskill 2.0.2
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 +123 -0
- package/README.vn.md +104 -0
- package/SKILL_GUIDE.vn.md +252 -0
- package/bin/devskill.js +11 -0
- package/meta.ts +123 -0
- package/package.json +21 -0
- package/publish.sh +50 -0
- package/scripts/cli.ts +556 -0
- package/skills/builderx_api-contexts/SKILL.md +63 -0
- package/skills/builderx_api-contexts/references/core-multi-outbox.md +57 -0
- package/skills/builderx_api-controllers/SKILL.md +49 -0
- package/skills/builderx_api-controllers/references/core-fallback.md +62 -0
- package/skills/builderx_api-schemas/SKILL.md +76 -0
- package/skills/builderx_api-schemas/references/core-schema.md +78 -0
- package/skills/builderx_spa-api/SKILL.md +67 -0
- package/skills/builderx_spa-api/references/base-api.md +97 -0
- package/skills/builderx_spa-api/references/fetch.md +70 -0
- package/skills/builderx_spa-design/SKILL.md +82 -0
- package/skills/builderx_spa-design/references/core-text-design.md +64 -0
- package/skills/builderx_spa-design/references/features-feedback-actions.md +76 -0
- package/skills/builderx_spa-design/references/features-forms.md +91 -0
- package/skills/builderx_spa-design/references/features-layout-navigation.md +121 -0
- package/skills/builderx_spa-permission/SKILL.md +38 -0
- package/skills/builderx_spa-permission/references/has-permission.md +34 -0
- package/skills/composition-patterns/AGENTS.md +946 -0
- package/skills/composition-patterns/README.md +60 -0
- package/skills/composition-patterns/SKILL.md +89 -0
- package/skills/composition-patterns/SYNC.md +5 -0
- package/skills/composition-patterns/metadata.json +11 -0
- package/skills/composition-patterns/rules/_sections.md +29 -0
- package/skills/composition-patterns/rules/_template.md +24 -0
- package/skills/composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
- package/skills/composition-patterns/rules/architecture-compound-components.md +112 -0
- package/skills/composition-patterns/rules/patterns-children-over-render-props.md +87 -0
- package/skills/composition-patterns/rules/patterns-explicit-variants.md +100 -0
- package/skills/composition-patterns/rules/react19-no-forwardref.md +42 -0
- package/skills/composition-patterns/rules/state-context-interface.md +191 -0
- package/skills/composition-patterns/rules/state-decouple-implementation.md +113 -0
- package/skills/composition-patterns/rules/state-lift-state.md +125 -0
- package/skills/deploy-to-vercel/Archive.zip +0 -0
- package/skills/deploy-to-vercel/SKILL.md +296 -0
- package/skills/deploy-to-vercel/SYNC.md +5 -0
- package/skills/deploy-to-vercel/resources/deploy-codex.sh +301 -0
- package/skills/deploy-to-vercel/resources/deploy.sh +301 -0
- package/skills/pinia/SKILL.md +105 -0
- package/skills/pinia/references/api-in-composables.md +139 -0
- package/skills/pinia/references/setup-stores.md +105 -0
- package/skills/pinia/references/using-in-components.md +91 -0
- package/skills/pinia-options/SKILL.md +72 -0
- package/skills/pinia-options/references/core-option-stores.md +149 -0
- package/skills/pinia-options/references/using-in-options-api.md +105 -0
- package/skills/react-best-practices/AGENTS.md +3373 -0
- package/skills/react-best-practices/README.md +123 -0
- package/skills/react-best-practices/SKILL.md +143 -0
- package/skills/react-best-practices/SYNC.md +5 -0
- package/skills/react-best-practices/metadata.json +15 -0
- package/skills/react-best-practices/rules/_sections.md +46 -0
- package/skills/react-best-practices/rules/_template.md +28 -0
- package/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/skills/react-best-practices/rules/advanced-init-once.md +42 -0
- package/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
- package/skills/react-best-practices/rules/async-api-routes.md +38 -0
- package/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/skills/react-best-practices/rules/async-dependencies.md +51 -0
- package/skills/react-best-practices/rules/async-parallel.md +28 -0
- package/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/skills/react-best-practices/rules/bundle-conditional.md +31 -0
- package/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/skills/react-best-practices/rules/bundle-preload.md +50 -0
- package/skills/react-best-practices/rules/client-event-listeners.md +74 -0
- package/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/skills/react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/skills/react-best-practices/rules/js-cache-storage.md +70 -0
- package/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/skills/react-best-practices/rules/js-flatmap-filter.md +60 -0
- package/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/skills/react-best-practices/rules/js-length-check-first.md +49 -0
- package/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/skills/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/skills/react-best-practices/rules/rendering-resource-hints.md +85 -0
- package/skills/react-best-practices/rules/rendering-script-defer-async.md +68 -0
- package/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/skills/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/skills/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/skills/react-best-practices/rules/rerender-no-inline-components.md +82 -0
- package/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/skills/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
- package/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/skills/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
- package/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/skills/react-best-practices/rules/server-auth-actions.md +96 -0
- package/skills/react-best-practices/rules/server-cache-lru.md +41 -0
- package/skills/react-best-practices/rules/server-cache-react.md +76 -0
- package/skills/react-best-practices/rules/server-dedup-props.md +65 -0
- package/skills/react-best-practices/rules/server-hoist-static-io.md +142 -0
- package/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/skills/react-best-practices/rules/server-serialization.md +38 -0
- package/skills/react-native-skills/AGENTS.md +2897 -0
- package/skills/react-native-skills/README.md +165 -0
- package/skills/react-native-skills/SKILL.md +121 -0
- package/skills/react-native-skills/SYNC.md +5 -0
- package/skills/react-native-skills/metadata.json +16 -0
- package/skills/react-native-skills/rules/_sections.md +86 -0
- package/skills/react-native-skills/rules/_template.md +28 -0
- package/skills/react-native-skills/rules/animation-derived-value.md +53 -0
- package/skills/react-native-skills/rules/animation-gesture-detector-press.md +95 -0
- package/skills/react-native-skills/rules/animation-gpu-properties.md +65 -0
- package/skills/react-native-skills/rules/design-system-compound-components.md +66 -0
- package/skills/react-native-skills/rules/fonts-config-plugin.md +71 -0
- package/skills/react-native-skills/rules/imports-design-system-folder.md +68 -0
- package/skills/react-native-skills/rules/js-hoist-intl.md +61 -0
- package/skills/react-native-skills/rules/list-performance-callbacks.md +44 -0
- package/skills/react-native-skills/rules/list-performance-function-references.md +132 -0
- package/skills/react-native-skills/rules/list-performance-images.md +53 -0
- package/skills/react-native-skills/rules/list-performance-inline-objects.md +97 -0
- package/skills/react-native-skills/rules/list-performance-item-expensive.md +94 -0
- package/skills/react-native-skills/rules/list-performance-item-memo.md +82 -0
- package/skills/react-native-skills/rules/list-performance-item-types.md +104 -0
- package/skills/react-native-skills/rules/list-performance-virtualize.md +67 -0
- package/skills/react-native-skills/rules/monorepo-native-deps-in-app.md +46 -0
- package/skills/react-native-skills/rules/monorepo-single-dependency-versions.md +63 -0
- package/skills/react-native-skills/rules/navigation-native-navigators.md +188 -0
- package/skills/react-native-skills/rules/react-compiler-destructure-functions.md +50 -0
- package/skills/react-native-skills/rules/react-compiler-reanimated-shared-values.md +48 -0
- package/skills/react-native-skills/rules/react-state-dispatcher.md +91 -0
- package/skills/react-native-skills/rules/react-state-fallback.md +56 -0
- package/skills/react-native-skills/rules/react-state-minimize.md +65 -0
- package/skills/react-native-skills/rules/rendering-no-falsy-and.md +74 -0
- package/skills/react-native-skills/rules/rendering-text-in-text-component.md +36 -0
- package/skills/react-native-skills/rules/scroll-position-no-state.md +82 -0
- package/skills/react-native-skills/rules/state-ground-truth.md +80 -0
- package/skills/react-native-skills/rules/ui-expo-image.md +66 -0
- package/skills/react-native-skills/rules/ui-image-gallery.md +104 -0
- package/skills/react-native-skills/rules/ui-measure-views.md +78 -0
- package/skills/react-native-skills/rules/ui-menus.md +174 -0
- package/skills/react-native-skills/rules/ui-native-modals.md +77 -0
- package/skills/react-native-skills/rules/ui-pressable.md +61 -0
- package/skills/react-native-skills/rules/ui-safe-area-scroll.md +65 -0
- package/skills/react-native-skills/rules/ui-scrollview-content-inset.md +45 -0
- package/skills/react-native-skills/rules/ui-styling.md +87 -0
- package/skills/slidev/LICENSE.md +21 -0
- package/skills/slidev/README.md +61 -0
- package/skills/slidev/SKILL.md +189 -0
- package/skills/slidev/SYNC.md +5 -0
- package/skills/slidev/references/animation-click-marker.md +37 -0
- package/skills/slidev/references/animation-drawing.md +68 -0
- package/skills/slidev/references/animation-rough-marker.md +53 -0
- package/skills/slidev/references/api-slide-hooks.md +37 -0
- package/skills/slidev/references/build-og-image.md +36 -0
- package/skills/slidev/references/build-pdf.md +40 -0
- package/skills/slidev/references/build-remote-assets.md +34 -0
- package/skills/slidev/references/build-seo-meta.md +43 -0
- package/skills/slidev/references/code-groups.md +64 -0
- package/skills/slidev/references/code-import-snippet.md +55 -0
- package/skills/slidev/references/code-line-highlighting.md +50 -0
- package/skills/slidev/references/code-line-numbers.md +46 -0
- package/skills/slidev/references/code-magic-move.md +57 -0
- package/skills/slidev/references/code-max-height.md +37 -0
- package/skills/slidev/references/code-twoslash.md +42 -0
- package/skills/slidev/references/core-animations.md +196 -0
- package/skills/slidev/references/core-cli.md +140 -0
- package/skills/slidev/references/core-components.md +197 -0
- package/skills/slidev/references/core-exporting.md +148 -0
- package/skills/slidev/references/core-frontmatter.md +195 -0
- package/skills/slidev/references/core-global-context.md +155 -0
- package/skills/slidev/references/core-headmatter.md +188 -0
- package/skills/slidev/references/core-hosting.md +152 -0
- package/skills/slidev/references/core-layouts.md +286 -0
- package/skills/slidev/references/core-syntax.md +155 -0
- package/skills/slidev/references/diagram-latex.md +55 -0
- package/skills/slidev/references/diagram-mermaid.md +44 -0
- package/skills/slidev/references/diagram-plantuml.md +45 -0
- package/skills/slidev/references/editor-monaco-run.md +44 -0
- package/skills/slidev/references/editor-monaco-write.md +24 -0
- package/skills/slidev/references/editor-monaco.md +50 -0
- package/skills/slidev/references/editor-prettier.md +40 -0
- package/skills/slidev/references/editor-side.md +23 -0
- package/skills/slidev/references/editor-vscode.md +55 -0
- package/skills/slidev/references/layout-canvas-size.md +25 -0
- package/skills/slidev/references/layout-draggable.md +57 -0
- package/skills/slidev/references/layout-global-layers.md +50 -0
- package/skills/slidev/references/layout-slots.md +75 -0
- package/skills/slidev/references/layout-transform.md +33 -0
- package/skills/slidev/references/layout-zoom.md +39 -0
- package/skills/slidev/references/presenter-notes-ruby.md +35 -0
- package/skills/slidev/references/presenter-recording.md +30 -0
- package/skills/slidev/references/presenter-remote.md +40 -0
- package/skills/slidev/references/presenter-timer.md +34 -0
- package/skills/slidev/references/style-direction.md +34 -0
- package/skills/slidev/references/style-icons.md +46 -0
- package/skills/slidev/references/style-scoped.md +50 -0
- package/skills/slidev/references/syntax-block-frontmatter.md +39 -0
- package/skills/slidev/references/syntax-frontmatter-merging.md +49 -0
- package/skills/slidev/references/syntax-importing-slides.md +60 -0
- package/skills/slidev/references/syntax-mdc.md +51 -0
- package/skills/slidev/references/tool-eject-theme.md +27 -0
- package/skills/tsdown/LICENSE.md +22 -0
- package/skills/tsdown/README.md +77 -0
- package/skills/tsdown/SKILL.md +407 -0
- package/skills/tsdown/SYNC.md +5 -0
- package/skills/tsdown/references/README.md +139 -0
- package/skills/tsdown/references/advanced-benchmark.md +8 -0
- package/skills/tsdown/references/advanced-ci.md +89 -0
- package/skills/tsdown/references/advanced-hooks.md +363 -0
- package/skills/tsdown/references/advanced-plugins.md +381 -0
- package/skills/tsdown/references/advanced-programmatic.md +378 -0
- package/skills/tsdown/references/advanced-rolldown-options.md +117 -0
- package/skills/tsdown/references/guide-getting-started.md +178 -0
- package/skills/tsdown/references/guide-introduction.md +42 -0
- package/skills/tsdown/references/guide-migrate-from-tsup.md +189 -0
- package/skills/tsdown/references/option-cjs-default.md +98 -0
- package/skills/tsdown/references/option-cleaning.md +275 -0
- package/skills/tsdown/references/option-config-file.md +281 -0
- package/skills/tsdown/references/option-css.md +301 -0
- package/skills/tsdown/references/option-dependencies.md +385 -0
- package/skills/tsdown/references/option-dts.md +251 -0
- package/skills/tsdown/references/option-entry.md +211 -0
- package/skills/tsdown/references/option-exe.md +120 -0
- package/skills/tsdown/references/option-lint.md +127 -0
- package/skills/tsdown/references/option-log-level.md +91 -0
- package/skills/tsdown/references/option-minification.md +177 -0
- package/skills/tsdown/references/option-output-directory.md +270 -0
- package/skills/tsdown/references/option-output-format.md +181 -0
- package/skills/tsdown/references/option-package-exports.md +320 -0
- package/skills/tsdown/references/option-platform.md +256 -0
- package/skills/tsdown/references/option-root.md +88 -0
- package/skills/tsdown/references/option-shims.md +299 -0
- package/skills/tsdown/references/option-sourcemap.md +301 -0
- package/skills/tsdown/references/option-target.md +222 -0
- package/skills/tsdown/references/option-tree-shaking.md +335 -0
- package/skills/tsdown/references/option-unbundle.md +310 -0
- package/skills/tsdown/references/option-watch-mode.md +261 -0
- package/skills/tsdown/references/recipe-react.md +338 -0
- package/skills/tsdown/references/recipe-solid.md +46 -0
- package/skills/tsdown/references/recipe-svelte.md +54 -0
- package/skills/tsdown/references/recipe-vue.md +387 -0
- package/skills/tsdown/references/recipe-wasm.md +125 -0
- package/skills/tsdown/references/reference-cli.md +472 -0
- package/skills/turborepo/LICENSE.md +7 -0
- package/skills/turborepo/SKILL.md +951 -0
- package/skills/turborepo/SYNC.md +5 -0
- package/skills/turborepo/command/turborepo.md +70 -0
- package/skills/turborepo/references/best-practices/RULE.md +241 -0
- package/skills/turborepo/references/best-practices/dependencies.md +246 -0
- package/skills/turborepo/references/best-practices/packages.md +335 -0
- package/skills/turborepo/references/best-practices/structure.md +297 -0
- package/skills/turborepo/references/boundaries/RULE.md +126 -0
- package/skills/turborepo/references/caching/RULE.md +153 -0
- package/skills/turborepo/references/caching/gotchas.md +190 -0
- package/skills/turborepo/references/caching/remote-cache.md +127 -0
- package/skills/turborepo/references/ci/RULE.md +79 -0
- package/skills/turborepo/references/ci/github-actions.md +162 -0
- package/skills/turborepo/references/ci/patterns.md +145 -0
- package/skills/turborepo/references/ci/vercel.md +103 -0
- package/skills/turborepo/references/cli/RULE.md +100 -0
- package/skills/turborepo/references/cli/commands.md +297 -0
- package/skills/turborepo/references/configuration/RULE.md +235 -0
- package/skills/turborepo/references/configuration/global-options.md +239 -0
- package/skills/turborepo/references/configuration/gotchas.md +368 -0
- package/skills/turborepo/references/configuration/tasks.md +325 -0
- package/skills/turborepo/references/environment/RULE.md +123 -0
- package/skills/turborepo/references/environment/gotchas.md +175 -0
- package/skills/turborepo/references/environment/modes.md +101 -0
- package/skills/turborepo/references/filtering/RULE.md +148 -0
- package/skills/turborepo/references/filtering/patterns.md +152 -0
- package/skills/turborepo/references/watch/RULE.md +99 -0
- package/skills/vercel-cli-with-tokens/SKILL.md +328 -0
- package/skills/vercel-cli-with-tokens/SYNC.md +5 -0
- package/skills/vue/SKILL.md +90 -0
- package/skills/vue/references/composables.md +54 -0
- package/skills/vue/references/lifecycle.md +31 -0
- package/skills/vue/references/props-emits.md +62 -0
- package/skills/vue/references/provide-inject.md +47 -0
- package/skills/vue/references/state.md +65 -0
- package/skills/vue-antdv-tailwind/SKILL.md +33 -0
- package/skills/vue-antdv-tailwind/references/styling-rules.md +61 -0
- package/skills/vue-best-practices/LICENSE.md +21 -0
- package/skills/vue-best-practices/SKILL.md +154 -0
- package/skills/vue-best-practices/SYNC.md +5 -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 +307 -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 +344 -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-jsx-best-practices/LICENSE.md +21 -0
- package/skills/vue-jsx-best-practices/SKILL.md +12 -0
- package/skills/vue-jsx-best-practices/SYNC.md +5 -0
- package/skills/vue-jsx-best-practices/reference/render-function-jsx-vue-vs-react.md +141 -0
- package/skills/vue-options/SKILL.md +98 -0
- package/skills/vue-options/references/lifecycle.md +107 -0
- package/skills/vue-options/references/mixins.md +96 -0
- package/skills/vue-options/references/props-emits.md +106 -0
- package/skills/vue-options/references/provide-inject.md +92 -0
- package/skills/vue-options/references/state.md +115 -0
- package/skills/vue-options-api-best-practices/LICENSE.md +21 -0
- package/skills/vue-options-api-best-practices/SKILL.md +23 -0
- package/skills/vue-options-api-best-practices/SYNC.md +5 -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/LICENSE.md +21 -0
- package/skills/vue-pinia-best-practices/SKILL.md +21 -0
- package/skills/vue-pinia-best-practices/SYNC.md +5 -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/LICENSE.md +21 -0
- package/skills/vue-router-best-practices/SKILL.md +23 -0
- package/skills/vue-router-best-practices/SYNC.md +5 -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/LICENSE.md +21 -0
- package/skills/vue-testing-best-practices/SKILL.md +29 -0
- package/skills/vue-testing-best-practices/SYNC.md +5 -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
- package/skills/vueuse-functions/LICENSE.md +21 -0
- package/skills/vueuse-functions/SKILL.md +419 -0
- package/skills/vueuse-functions/SYNC.md +5 -0
- package/skills/vueuse-functions/references/computedAsync.md +195 -0
- package/skills/vueuse-functions/references/computedEager.md +62 -0
- package/skills/vueuse-functions/references/computedInject.md +137 -0
- package/skills/vueuse-functions/references/computedWithControl.md +98 -0
- package/skills/vueuse-functions/references/createEventHook.md +86 -0
- package/skills/vueuse-functions/references/createGenericProjection.md +25 -0
- package/skills/vueuse-functions/references/createGlobalState.md +95 -0
- package/skills/vueuse-functions/references/createInjectionState.md +215 -0
- package/skills/vueuse-functions/references/createProjection.md +31 -0
- package/skills/vueuse-functions/references/createRef.md +54 -0
- package/skills/vueuse-functions/references/createReusableTemplate.md +357 -0
- package/skills/vueuse-functions/references/createSharedComposable.md +42 -0
- package/skills/vueuse-functions/references/createTemplatePromise.md +306 -0
- package/skills/vueuse-functions/references/createUnrefFn.md +51 -0
- package/skills/vueuse-functions/references/extendRef.md +76 -0
- package/skills/vueuse-functions/references/from.md +80 -0
- package/skills/vueuse-functions/references/get.md +30 -0
- package/skills/vueuse-functions/references/injectLocal.md +35 -0
- package/skills/vueuse-functions/references/isDefined.md +31 -0
- package/skills/vueuse-functions/references/logicAnd.md +40 -0
- package/skills/vueuse-functions/references/logicNot.md +36 -0
- package/skills/vueuse-functions/references/logicOr.md +40 -0
- package/skills/vueuse-functions/references/makeDestructurable.md +41 -0
- package/skills/vueuse-functions/references/onClickOutside.md +221 -0
- package/skills/vueuse-functions/references/onElementRemoval.md +88 -0
- package/skills/vueuse-functions/references/onKeyStroke.md +211 -0
- package/skills/vueuse-functions/references/onLongPress.md +227 -0
- package/skills/vueuse-functions/references/onStartTyping.md +53 -0
- package/skills/vueuse-functions/references/provideLocal.md +37 -0
- package/skills/vueuse-functions/references/reactify.md +144 -0
- package/skills/vueuse-functions/references/reactifyObject.md +62 -0
- package/skills/vueuse-functions/references/reactiveComputed.md +34 -0
- package/skills/vueuse-functions/references/reactiveOmit.md +86 -0
- package/skills/vueuse-functions/references/reactivePick.md +106 -0
- package/skills/vueuse-functions/references/refAutoReset.md +46 -0
- package/skills/vueuse-functions/references/refDebounced.md +81 -0
- package/skills/vueuse-functions/references/refDefault.md +36 -0
- package/skills/vueuse-functions/references/refManualReset.md +44 -0
- package/skills/vueuse-functions/references/refThrottled.md +99 -0
- package/skills/vueuse-functions/references/refWithControl.md +146 -0
- package/skills/vueuse-functions/references/set.md +30 -0
- package/skills/vueuse-functions/references/syncRef.md +195 -0
- package/skills/vueuse-functions/references/syncRefs.md +128 -0
- package/skills/vueuse-functions/references/templateRef.md +86 -0
- package/skills/vueuse-functions/references/toObserver.md +38 -0
- package/skills/vueuse-functions/references/toReactive.md +41 -0
- package/skills/vueuse-functions/references/toRef.md +75 -0
- package/skills/vueuse-functions/references/toRefs.md +81 -0
- package/skills/vueuse-functions/references/tryOnBeforeMount.md +34 -0
- package/skills/vueuse-functions/references/tryOnBeforeUnmount.md +32 -0
- package/skills/vueuse-functions/references/tryOnMounted.md +34 -0
- package/skills/vueuse-functions/references/tryOnScopeDispose.md +31 -0
- package/skills/vueuse-functions/references/tryOnUnmounted.md +32 -0
- package/skills/vueuse-functions/references/unrefElement.md +54 -0
- package/skills/vueuse-functions/references/until.md +161 -0
- package/skills/vueuse-functions/references/useAbs.md +31 -0
- package/skills/vueuse-functions/references/useActiveElement.md +85 -0
- package/skills/vueuse-functions/references/useAnimate.md +181 -0
- package/skills/vueuse-functions/references/useArrayDifference.md +84 -0
- package/skills/vueuse-functions/references/useArrayEvery.md +59 -0
- package/skills/vueuse-functions/references/useArrayFilter.md +63 -0
- package/skills/vueuse-functions/references/useArrayFind.md +50 -0
- package/skills/vueuse-functions/references/useArrayFindIndex.md +59 -0
- package/skills/vueuse-functions/references/useArrayFindLast.md +52 -0
- package/skills/vueuse-functions/references/useArrayIncludes.md +63 -0
- package/skills/vueuse-functions/references/useArrayJoin.md +74 -0
- package/skills/vueuse-functions/references/useArrayMap.md +59 -0
- package/skills/vueuse-functions/references/useArrayReduce.md +81 -0
- package/skills/vueuse-functions/references/useArraySome.md +59 -0
- package/skills/vueuse-functions/references/useArrayUnique.md +76 -0
- package/skills/vueuse-functions/references/useAsyncQueue.md +136 -0
- package/skills/vueuse-functions/references/useAsyncState.md +185 -0
- package/skills/vueuse-functions/references/useAsyncValidator.md +70 -0
- package/skills/vueuse-functions/references/useAuth.md +123 -0
- package/skills/vueuse-functions/references/useAverage.md +36 -0
- package/skills/vueuse-functions/references/useAxios.md +325 -0
- package/skills/vueuse-functions/references/useBase64.md +136 -0
- package/skills/vueuse-functions/references/useBattery.md +78 -0
- package/skills/vueuse-functions/references/useBluetooth.md +175 -0
- package/skills/vueuse-functions/references/useBreakpoints.md +172 -0
- package/skills/vueuse-functions/references/useBroadcastChannel.md +74 -0
- package/skills/vueuse-functions/references/useBrowserLocation.md +83 -0
- package/skills/vueuse-functions/references/useCached.md +52 -0
- package/skills/vueuse-functions/references/useCeil.md +31 -0
- package/skills/vueuse-functions/references/useChangeCase.md +79 -0
- package/skills/vueuse-functions/references/useClamp.md +85 -0
- package/skills/vueuse-functions/references/useClipboard.md +123 -0
- package/skills/vueuse-functions/references/useClipboardItems.md +94 -0
- package/skills/vueuse-functions/references/useCloned.md +91 -0
- package/skills/vueuse-functions/references/useColorMode.md +172 -0
- package/skills/vueuse-functions/references/useConfirmDialog.md +159 -0
- package/skills/vueuse-functions/references/useCookies.md +162 -0
- package/skills/vueuse-functions/references/useCountdown.md +105 -0
- package/skills/vueuse-functions/references/useCounter.md +86 -0
- package/skills/vueuse-functions/references/useCssSupports.md +35 -0
- package/skills/vueuse-functions/references/useCssVar.md +50 -0
- package/skills/vueuse-functions/references/useCurrentElement.md +61 -0
- package/skills/vueuse-functions/references/useCycleList.md +75 -0
- package/skills/vueuse-functions/references/useDark.md +144 -0
- package/skills/vueuse-functions/references/useDateFormat.md +145 -0
- package/skills/vueuse-functions/references/useDebounceFn.md +100 -0
- package/skills/vueuse-functions/references/useDebouncedRefHistory.md +40 -0
- package/skills/vueuse-functions/references/useDeviceMotion.md +86 -0
- package/skills/vueuse-functions/references/useDeviceOrientation.md +62 -0
- package/skills/vueuse-functions/references/useDevicePixelRatio.md +44 -0
- package/skills/vueuse-functions/references/useDevicesList.md +90 -0
- package/skills/vueuse-functions/references/useDisplayMedia.md +71 -0
- package/skills/vueuse-functions/references/useDocumentVisibility.md +45 -0
- package/skills/vueuse-functions/references/useDraggable.md +317 -0
- package/skills/vueuse-functions/references/useDrauu.md +65 -0
- package/skills/vueuse-functions/references/useDropZone.md +83 -0
- package/skills/vueuse-functions/references/useElementBounding.md +131 -0
- package/skills/vueuse-functions/references/useElementByPoint.md +48 -0
- package/skills/vueuse-functions/references/useElementHover.md +79 -0
- package/skills/vueuse-functions/references/useElementSize.md +78 -0
- package/skills/vueuse-functions/references/useElementVisibility.md +123 -0
- package/skills/vueuse-functions/references/useEventBus.md +101 -0
- package/skills/vueuse-functions/references/useEventListener.md +226 -0
- package/skills/vueuse-functions/references/useEventSource.md +204 -0
- package/skills/vueuse-functions/references/useExtractedObservable.md +198 -0
- package/skills/vueuse-functions/references/useEyeDropper.md +71 -0
- package/skills/vueuse-functions/references/useFavicon.md +67 -0
- package/skills/vueuse-functions/references/useFetch.md +546 -0
- package/skills/vueuse-functions/references/useFileDialog.md +91 -0
- package/skills/vueuse-functions/references/useFileSystemAccess.md +162 -0
- package/skills/vueuse-functions/references/useFirestore.md +129 -0
- package/skills/vueuse-functions/references/useFloor.md +31 -0
- package/skills/vueuse-functions/references/useFocus.md +99 -0
- package/skills/vueuse-functions/references/useFocusTrap.md +245 -0
- package/skills/vueuse-functions/references/useFocusWithin.md +57 -0
- package/skills/vueuse-functions/references/useFps.md +28 -0
- package/skills/vueuse-functions/references/useFullscreen.md +75 -0
- package/skills/vueuse-functions/references/useFuse.md +107 -0
- package/skills/vueuse-functions/references/useGamepad.md +222 -0
- package/skills/vueuse-functions/references/useGeolocation.md +85 -0
- package/skills/vueuse-functions/references/useIDBKeyval.md +93 -0
- package/skills/vueuse-functions/references/useIdle.md +88 -0
- package/skills/vueuse-functions/references/useImage.md +86 -0
- package/skills/vueuse-functions/references/useInfiniteScroll.md +157 -0
- package/skills/vueuse-functions/references/useIntersectionObserver.md +118 -0
- package/skills/vueuse-functions/references/useInterval.md +112 -0
- package/skills/vueuse-functions/references/useIntervalFn.md +50 -0
- package/skills/vueuse-functions/references/useIpcRenderer.md +144 -0
- package/skills/vueuse-functions/references/useIpcRendererInvoke.md +58 -0
- package/skills/vueuse-functions/references/useIpcRendererOn.md +52 -0
- package/skills/vueuse-functions/references/useJwt.md +57 -0
- package/skills/vueuse-functions/references/useKeyModifier.md +87 -0
- package/skills/vueuse-functions/references/useLastChanged.md +63 -0
- package/skills/vueuse-functions/references/useLocalStorage.md +41 -0
- package/skills/vueuse-functions/references/useMagicKeys.md +245 -0
- package/skills/vueuse-functions/references/useManualRefHistory.md +204 -0
- package/skills/vueuse-functions/references/useMath.md +47 -0
- package/skills/vueuse-functions/references/useMax.md +36 -0
- package/skills/vueuse-functions/references/useMediaControls.md +571 -0
- package/skills/vueuse-functions/references/useMediaQuery.md +53 -0
- package/skills/vueuse-functions/references/useMemoize.md +175 -0
- package/skills/vueuse-functions/references/useMemory.md +71 -0
- package/skills/vueuse-functions/references/useMin.md +36 -0
- package/skills/vueuse-functions/references/useMounted.md +38 -0
- package/skills/vueuse-functions/references/useMouse.md +113 -0
- package/skills/vueuse-functions/references/useMouseInElement.md +123 -0
- package/skills/vueuse-functions/references/useMousePressed.md +112 -0
- package/skills/vueuse-functions/references/useMutationObserver.md +61 -0
- package/skills/vueuse-functions/references/useNProgress.md +78 -0
- package/skills/vueuse-functions/references/useNavigatorLanguage.md +57 -0
- package/skills/vueuse-functions/references/useNetwork.md +106 -0
- package/skills/vueuse-functions/references/useNow.md +79 -0
- package/skills/vueuse-functions/references/useObjectUrl.md +55 -0
- package/skills/vueuse-functions/references/useObservable.md +91 -0
- package/skills/vueuse-functions/references/useOffsetPagination.md +199 -0
- package/skills/vueuse-functions/references/useOnline.md +41 -0
- package/skills/vueuse-functions/references/usePageLeave.md +42 -0
- package/skills/vueuse-functions/references/useParallax.md +58 -0
- package/skills/vueuse-functions/references/useParentElement.md +54 -0
- package/skills/vueuse-functions/references/usePerformanceObserver.md +48 -0
- package/skills/vueuse-functions/references/usePermission.md +79 -0
- package/skills/vueuse-functions/references/usePointer.md +89 -0
- package/skills/vueuse-functions/references/usePointerLock.md +60 -0
- package/skills/vueuse-functions/references/usePointerSwipe.md +80 -0
- package/skills/vueuse-functions/references/usePrecision.md +49 -0
- package/skills/vueuse-functions/references/usePreferredColorScheme.md +42 -0
- package/skills/vueuse-functions/references/usePreferredContrast.md +42 -0
- package/skills/vueuse-functions/references/usePreferredDark.md +41 -0
- package/skills/vueuse-functions/references/usePreferredLanguages.md +41 -0
- package/skills/vueuse-functions/references/usePreferredReducedMotion.md +42 -0
- package/skills/vueuse-functions/references/usePreferredReducedTransparency.md +42 -0
- package/skills/vueuse-functions/references/usePrevious.md +40 -0
- package/skills/vueuse-functions/references/useProjection.md +38 -0
- package/skills/vueuse-functions/references/useQRCode.md +53 -0
- package/skills/vueuse-functions/references/useRTDB.md +83 -0
- package/skills/vueuse-functions/references/useRafFn.md +68 -0
- package/skills/vueuse-functions/references/useRefHistory.md +285 -0
- package/skills/vueuse-functions/references/useResizeObserver.md +109 -0
- package/skills/vueuse-functions/references/useRound.md +31 -0
- package/skills/vueuse-functions/references/useRouteHash.md +27 -0
- package/skills/vueuse-functions/references/useRouteParams.md +38 -0
- package/skills/vueuse-functions/references/useRouteQuery.md +79 -0
- package/skills/vueuse-functions/references/useSSRWidth.md +47 -0
- package/skills/vueuse-functions/references/useScreenOrientation.md +96 -0
- package/skills/vueuse-functions/references/useScreenSafeArea.md +60 -0
- package/skills/vueuse-functions/references/useScriptTag.md +116 -0
- package/skills/vueuse-functions/references/useScroll.md +238 -0
- package/skills/vueuse-functions/references/useScrollLock.md +66 -0
- package/skills/vueuse-functions/references/useSessionStorage.md +41 -0
- package/skills/vueuse-functions/references/useShare.md +68 -0
- package/skills/vueuse-functions/references/useSortable.md +235 -0
- package/skills/vueuse-functions/references/useSorted.md +90 -0
- package/skills/vueuse-functions/references/useSpeechRecognition.md +94 -0
- package/skills/vueuse-functions/references/useSpeechSynthesis.md +105 -0
- package/skills/vueuse-functions/references/useStepper.md +137 -0
- package/skills/vueuse-functions/references/useStorage.md +278 -0
- package/skills/vueuse-functions/references/useStorageAsync.md +136 -0
- package/skills/vueuse-functions/references/useStyleTag.md +131 -0
- package/skills/vueuse-functions/references/useSubject.md +77 -0
- package/skills/vueuse-functions/references/useSubscription.md +33 -0
- package/skills/vueuse-functions/references/useSum.md +36 -0
- package/skills/vueuse-functions/references/useSupported.md +29 -0
- package/skills/vueuse-functions/references/useSwipe.md +75 -0
- package/skills/vueuse-functions/references/useTemplateRefsList.md +37 -0
- package/skills/vueuse-functions/references/useTextDirection.md +75 -0
- package/skills/vueuse-functions/references/useTextSelection.md +40 -0
- package/skills/vueuse-functions/references/useTextareaAutosize.md +97 -0
- package/skills/vueuse-functions/references/useThrottleFn.md +57 -0
- package/skills/vueuse-functions/references/useThrottledRefHistory.md +47 -0
- package/skills/vueuse-functions/references/useTimeAgo.md +154 -0
- package/skills/vueuse-functions/references/useTimeAgoIntl.md +117 -0
- package/skills/vueuse-functions/references/useTimeout.md +113 -0
- package/skills/vueuse-functions/references/useTimeoutFn.md +51 -0
- package/skills/vueuse-functions/references/useTimeoutPoll.md +47 -0
- package/skills/vueuse-functions/references/useTimestamp.md +89 -0
- package/skills/vueuse-functions/references/useTitle.md +113 -0
- package/skills/vueuse-functions/references/useToNumber.md +54 -0
- package/skills/vueuse-functions/references/useToString.md +34 -0
- package/skills/vueuse-functions/references/useToggle.md +103 -0
- package/skills/vueuse-functions/references/useTransition.md +265 -0
- package/skills/vueuse-functions/references/useTrunc.md +33 -0
- package/skills/vueuse-functions/references/useUrlSearchParams.md +121 -0
- package/skills/vueuse-functions/references/useUserMedia.md +1138 -0
- package/skills/vueuse-functions/references/useVModel.md +182 -0
- package/skills/vueuse-functions/references/useVModels.md +67 -0
- package/skills/vueuse-functions/references/useVibrate.md +87 -0
- package/skills/vueuse-functions/references/useVirtualList.md +182 -0
- package/skills/vueuse-functions/references/useWakeLock.md +50 -0
- package/skills/vueuse-functions/references/useWebNotification.md +176 -0
- package/skills/vueuse-functions/references/useWebSocket.md +299 -0
- package/skills/vueuse-functions/references/useWebWorker.md +60 -0
- package/skills/vueuse-functions/references/useWebWorkerFn.md +102 -0
- package/skills/vueuse-functions/references/useWindowFocus.md +46 -0
- package/skills/vueuse-functions/references/useWindowScroll.md +61 -0
- package/skills/vueuse-functions/references/useWindowSize.md +76 -0
- package/skills/vueuse-functions/references/useZoomFactor.md +53 -0
- package/skills/vueuse-functions/references/useZoomLevel.md +53 -0
- package/skills/vueuse-functions/references/watchArray.md +53 -0
- package/skills/vueuse-functions/references/watchAtMost.md +55 -0
- package/skills/vueuse-functions/references/watchDebounced.md +101 -0
- package/skills/vueuse-functions/references/watchDeep.md +54 -0
- package/skills/vueuse-functions/references/watchExtractedObservable.md +192 -0
- package/skills/vueuse-functions/references/watchIgnorable.md +120 -0
- package/skills/vueuse-functions/references/watchImmediate.md +44 -0
- package/skills/vueuse-functions/references/watchOnce.md +41 -0
- package/skills/vueuse-functions/references/watchPausable.md +86 -0
- package/skills/vueuse-functions/references/watchThrottled.md +108 -0
- package/skills/vueuse-functions/references/watchTriggerable.md +98 -0
- package/skills/vueuse-functions/references/watchWithFilter.md +54 -0
- package/skills/vueuse-functions/references/whenever.md +100 -0
- package/skills/web-design-guidelines/SKILL.md +39 -0
- package/skills/web-design-guidelines/SYNC.md +5 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Component Data Flow Best Practices
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: Clear data flow between components prevents state bugs, stale UI, and brittle coupling
|
|
5
|
+
type: best-practice
|
|
6
|
+
tags: [vue3, props, emits, v-model, provide-inject, data-flow, typescript]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Component Data Flow Best Practices
|
|
10
|
+
|
|
11
|
+
**Impact: HIGH** - Vue components stay reliable when data flow is explicit: props go down, events go up, `v-model` handles two-way bindings, and provide/inject supports cross-tree dependencies. Blurring these boundaries leads to stale state, hidden coupling, and hard-to-debug UI.
|
|
12
|
+
|
|
13
|
+
The main principle of data flow in Vue.js is **Props Down / Events Up**. This is the most maintainable default, and one-way flow scales well.
|
|
14
|
+
|
|
15
|
+
## Task List
|
|
16
|
+
|
|
17
|
+
- Treat props as read-only inputs
|
|
18
|
+
- Use props/emit for component communication; reserve refs for imperative actions
|
|
19
|
+
- When refs are required for imperative APIs, type them with template refs
|
|
20
|
+
- Emit events instead of mutating parent state directly
|
|
21
|
+
- Use `defineModel` for v-model in modern Vue (3.4+)
|
|
22
|
+
- Handle v-model modifiers deliberately in child components
|
|
23
|
+
- Use symbols for provide/inject keys to avoid props drilling (over ~3 layers)
|
|
24
|
+
- Keep mutations in the provider or expose explicit actions
|
|
25
|
+
- In TypeScript projects, prefer type-based `defineProps`, `defineEmits`, and `InjectionKey`
|
|
26
|
+
|
|
27
|
+
## Props: One-Way Data Down
|
|
28
|
+
|
|
29
|
+
Props are inputs. Do not mutate them in the child.
|
|
30
|
+
|
|
31
|
+
**BAD:**
|
|
32
|
+
```vue
|
|
33
|
+
<script setup>
|
|
34
|
+
const props = defineProps({ count: Number })
|
|
35
|
+
|
|
36
|
+
function increment() {
|
|
37
|
+
props.count++
|
|
38
|
+
}
|
|
39
|
+
</script>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**GOOD:**
|
|
43
|
+
|
|
44
|
+
If state needs to change, emit an event, use `v-model` or create a local copy.
|
|
45
|
+
|
|
46
|
+
## Prefer props/emit over component refs
|
|
47
|
+
|
|
48
|
+
**BAD:**
|
|
49
|
+
```vue
|
|
50
|
+
<script setup>
|
|
51
|
+
import { ref } from 'vue'
|
|
52
|
+
import UserForm from './UserForm.vue'
|
|
53
|
+
|
|
54
|
+
const formRef = ref(null)
|
|
55
|
+
|
|
56
|
+
function submitForm() {
|
|
57
|
+
if (formRef.value.isValid) {
|
|
58
|
+
formRef.value.submit()
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<template>
|
|
64
|
+
<UserForm ref="formRef" />
|
|
65
|
+
<button @click="submitForm">Submit</button>
|
|
66
|
+
</template>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**GOOD:**
|
|
70
|
+
```vue
|
|
71
|
+
<script setup>
|
|
72
|
+
import UserForm from './UserForm.vue'
|
|
73
|
+
|
|
74
|
+
function handleSubmit(formData) {
|
|
75
|
+
api.submit(formData)
|
|
76
|
+
}
|
|
77
|
+
</script>
|
|
78
|
+
|
|
79
|
+
<template>
|
|
80
|
+
<UserForm @submit="handleSubmit" />
|
|
81
|
+
</template>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Type component refs when imperative access is required
|
|
85
|
+
|
|
86
|
+
Prefer props/emits by default. When a parent must call an exposed child method, type the ref explicitly and expose only the intended API from the child with `defineExpose`.
|
|
87
|
+
|
|
88
|
+
**BAD:**
|
|
89
|
+
```vue
|
|
90
|
+
<script setup lang="ts">
|
|
91
|
+
import { ref, onMounted } from 'vue'
|
|
92
|
+
import DialogPanel from './DialogPanel.vue'
|
|
93
|
+
|
|
94
|
+
const panelRef = ref(null)
|
|
95
|
+
|
|
96
|
+
onMounted(() => {
|
|
97
|
+
panelRef.value.open()
|
|
98
|
+
})
|
|
99
|
+
</script>
|
|
100
|
+
|
|
101
|
+
<template>
|
|
102
|
+
<DialogPanel ref="panelRef" />
|
|
103
|
+
</template>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**GOOD:**
|
|
107
|
+
```vue
|
|
108
|
+
<!-- DialogPanel.vue -->
|
|
109
|
+
<script setup lang="ts">
|
|
110
|
+
function open() {}
|
|
111
|
+
|
|
112
|
+
defineExpose({ open })
|
|
113
|
+
</script>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```vue
|
|
117
|
+
<!-- Parent.vue -->
|
|
118
|
+
<script setup lang="ts">
|
|
119
|
+
import { onMounted, useTemplateRef } from 'vue'
|
|
120
|
+
import DialogPanel from './DialogPanel.vue'
|
|
121
|
+
|
|
122
|
+
// Vue 3.5+ with useTemplateRef
|
|
123
|
+
const panelRef = useTemplateRef('panelRef')
|
|
124
|
+
|
|
125
|
+
// Before Vue 3.5 with manual typing and ref
|
|
126
|
+
// const panelRef = ref<InstanceType<typeof DialogPanel> | null>(null)
|
|
127
|
+
|
|
128
|
+
onMounted(() => {
|
|
129
|
+
panelRef.value?.open()
|
|
130
|
+
})
|
|
131
|
+
</script>
|
|
132
|
+
|
|
133
|
+
<template>
|
|
134
|
+
<DialogPanel ref="panelRef" />
|
|
135
|
+
</template>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Emits: Explicit Events Up
|
|
139
|
+
|
|
140
|
+
Component events do not bubble. If a parent needs to know about an event, re-emit it explicitly.
|
|
141
|
+
|
|
142
|
+
**BAD:**
|
|
143
|
+
```vue
|
|
144
|
+
<!-- Parent expects "saved" from grandchild, but it won't bubble -->
|
|
145
|
+
<Child @saved="onSaved" />
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**GOOD:**
|
|
149
|
+
```vue
|
|
150
|
+
<!-- Child.vue -->
|
|
151
|
+
<script setup>
|
|
152
|
+
const emit = defineEmits(['saved'])
|
|
153
|
+
|
|
154
|
+
function onGrandchildSaved(payload) {
|
|
155
|
+
emit('saved', payload)
|
|
156
|
+
}
|
|
157
|
+
</script>
|
|
158
|
+
|
|
159
|
+
<template>
|
|
160
|
+
<Grandchild @saved="onGrandchildSaved" />
|
|
161
|
+
</template>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Event naming:** use kebab-case in templates and camelCase in script:
|
|
165
|
+
```vue
|
|
166
|
+
<script setup>
|
|
167
|
+
const emit = defineEmits(['updateUser'])
|
|
168
|
+
</script>
|
|
169
|
+
|
|
170
|
+
<template>
|
|
171
|
+
<ProfileForm @update-user="emit('updateUser', $event)" />
|
|
172
|
+
</template>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## `v-model`: Predictable Two-Way Bindings
|
|
176
|
+
|
|
177
|
+
Use `defineModel` by default for component bindings and emit updates on input. Only use the `modelValue` + `update:modelValue` pattern if you are on Vue < 3.4.
|
|
178
|
+
|
|
179
|
+
**BAD:**
|
|
180
|
+
```vue
|
|
181
|
+
<script setup>
|
|
182
|
+
const props = defineProps({ value: String })
|
|
183
|
+
</script>
|
|
184
|
+
|
|
185
|
+
<template>
|
|
186
|
+
<input :value="props.value" @input="$emit('input', $event.target.value)" />
|
|
187
|
+
</template>
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**GOOD (Vue 3.4+):**
|
|
191
|
+
```vue
|
|
192
|
+
<script setup>
|
|
193
|
+
const model = defineModel({ type: String })
|
|
194
|
+
</script>
|
|
195
|
+
|
|
196
|
+
<template>
|
|
197
|
+
<input v-model="model" />
|
|
198
|
+
</template>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**GOOD (Vue < 3.4):**
|
|
202
|
+
```vue
|
|
203
|
+
<script setup>
|
|
204
|
+
const props = defineProps({ modelValue: String })
|
|
205
|
+
const emit = defineEmits(['update:modelValue'])
|
|
206
|
+
</script>
|
|
207
|
+
|
|
208
|
+
<template>
|
|
209
|
+
<input
|
|
210
|
+
:value="props.modelValue"
|
|
211
|
+
@input="emit('update:modelValue', $event.target.value)"
|
|
212
|
+
/>
|
|
213
|
+
</template>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
If you need the updated value immediately after a change, use the input event value or `nextTick` in the parent.
|
|
217
|
+
|
|
218
|
+
## Provide/Inject: Shared Context Without Prop Drilling
|
|
219
|
+
|
|
220
|
+
Use provide/inject for cross-tree state, but keep mutations centralized in the provider and expose explicit actions.
|
|
221
|
+
|
|
222
|
+
**BAD:**
|
|
223
|
+
```vue
|
|
224
|
+
// Provider.vue
|
|
225
|
+
provide('theme', reactive({ dark: false }))
|
|
226
|
+
|
|
227
|
+
// Consumer.vue
|
|
228
|
+
const theme = inject('theme')
|
|
229
|
+
// Mutating shared state from any depth becomes hard to track
|
|
230
|
+
theme.dark = true
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**GOOD:**
|
|
234
|
+
```vue
|
|
235
|
+
// Provider.vue
|
|
236
|
+
const theme = reactive({ dark: false })
|
|
237
|
+
const toggleTheme = () => { theme.dark = !theme.dark }
|
|
238
|
+
|
|
239
|
+
provide(themeKey, readonly(theme))
|
|
240
|
+
provide(themeActionsKey, { toggleTheme })
|
|
241
|
+
|
|
242
|
+
// Consumer.vue
|
|
243
|
+
const theme = inject(themeKey)
|
|
244
|
+
const { toggleTheme } = inject(themeActionsKey)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Use symbols for keys to avoid collisions in large apps:
|
|
248
|
+
```ts
|
|
249
|
+
export const themeKey = Symbol('theme')
|
|
250
|
+
export const themeActionsKey = Symbol('theme-actions')
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Use TypeScript Contracts for Public Component APIs
|
|
254
|
+
|
|
255
|
+
In TypeScript projects, type component boundaries directly with `defineProps`, `defineEmits`, and `InjectionKey` so invalid payloads and mismatched injections fail at compile time.
|
|
256
|
+
|
|
257
|
+
**BAD:**
|
|
258
|
+
```vue
|
|
259
|
+
<script setup lang="ts">
|
|
260
|
+
import { inject } from 'vue'
|
|
261
|
+
|
|
262
|
+
const props = defineProps({
|
|
263
|
+
userId: String
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
const emit = defineEmits(['save'])
|
|
267
|
+
const settings = inject('settings')
|
|
268
|
+
|
|
269
|
+
// Payload shape is not checked here
|
|
270
|
+
emit('save', 123)
|
|
271
|
+
|
|
272
|
+
// Key is string-based and not type-safe
|
|
273
|
+
settings?.theme = 'dark'
|
|
274
|
+
</script>
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**GOOD:**
|
|
278
|
+
```vue
|
|
279
|
+
<script setup lang="ts">
|
|
280
|
+
import { inject, provide } from 'vue'
|
|
281
|
+
import type { InjectionKey } from 'vue'
|
|
282
|
+
|
|
283
|
+
interface Props {
|
|
284
|
+
userId: string
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
interface Emits {
|
|
288
|
+
save: [payload: { id: string; draft: boolean }]
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
interface Settings {
|
|
292
|
+
theme: 'light' | 'dark'
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const settingsKey: InjectionKey<Settings> = Symbol('settings')
|
|
296
|
+
|
|
297
|
+
const props = defineProps<Props>()
|
|
298
|
+
const emit = defineEmits<Emits>()
|
|
299
|
+
|
|
300
|
+
provide(settingsKey, { theme: 'light' })
|
|
301
|
+
|
|
302
|
+
const settings = inject(settingsKey)
|
|
303
|
+
if (settings) {
|
|
304
|
+
emit('save', { id: props.userId, draft: false })
|
|
305
|
+
}
|
|
306
|
+
</script>
|
|
307
|
+
```
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Component Fallthrough Attributes Best Practices
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: Incorrect $attrs access and reactivity assumptions can cause undefined values and watchers that never run
|
|
5
|
+
type: best-practice
|
|
6
|
+
tags: [vue3, attrs, fallthrough-attributes, composition-api, reactivity]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Component Fallthrough Attributes Best Practices
|
|
10
|
+
|
|
11
|
+
**Impact: MEDIUM** - Fallthrough attributes are straightforward once you follow Vue's conventions: hyphenated names use bracket notation, listener keys are camelCase `onX`, and `useAttrs()` is current-but-not-reactive.
|
|
12
|
+
|
|
13
|
+
## Task List
|
|
14
|
+
|
|
15
|
+
- Access hyphenated attribute names with bracket notation (for example `attrs['data-testid']`)
|
|
16
|
+
- Access event listeners with camelCase `onX` keys (for example `attrs.onClick`)
|
|
17
|
+
- Do not `watch()` values returned from `useAttrs()`; those watchers do not trigger on attr changes
|
|
18
|
+
- Use `onUpdated()` for attr-driven side effects
|
|
19
|
+
- Promote frequently observed attrs to props when reactive observation is required
|
|
20
|
+
|
|
21
|
+
## Access Attribute and Listener Keys Correctly
|
|
22
|
+
|
|
23
|
+
Hyphenated attribute names preserve their original casing in JavaScript, so dot notation does not work for keys that include `-`.
|
|
24
|
+
|
|
25
|
+
**BAD:**
|
|
26
|
+
```vue
|
|
27
|
+
<script setup>
|
|
28
|
+
import { useAttrs } from 'vue'
|
|
29
|
+
|
|
30
|
+
const attrs = useAttrs()
|
|
31
|
+
|
|
32
|
+
console.log(attrs.data-testid) // Syntax error
|
|
33
|
+
console.log(attrs.dataTestid) // undefined for data-testid
|
|
34
|
+
console.log(attrs['on-click']) // undefined
|
|
35
|
+
console.log(attrs['@click']) // undefined
|
|
36
|
+
</script>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**GOOD:**
|
|
40
|
+
```vue
|
|
41
|
+
<script setup>
|
|
42
|
+
import { useAttrs } from 'vue'
|
|
43
|
+
|
|
44
|
+
const attrs = useAttrs()
|
|
45
|
+
|
|
46
|
+
console.log(attrs['data-testid'])
|
|
47
|
+
console.log(attrs['aria-label'])
|
|
48
|
+
console.log(attrs['foo-bar'])
|
|
49
|
+
|
|
50
|
+
console.log(attrs.onClick)
|
|
51
|
+
console.log(attrs.onCustomEvent)
|
|
52
|
+
console.log(attrs.onMouseEnter)
|
|
53
|
+
</script>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Naming Reference
|
|
57
|
+
|
|
58
|
+
| Parent Usage | Access in `attrs` |
|
|
59
|
+
|--------------|-------------------|
|
|
60
|
+
| `class="foo"` | `attrs.class` |
|
|
61
|
+
| `data-id="123"` | `attrs['data-id']` |
|
|
62
|
+
| `aria-label="..."` | `attrs['aria-label']` |
|
|
63
|
+
| `foo-bar="baz"` | `attrs['foo-bar']` |
|
|
64
|
+
| `@click="fn"` | `attrs.onClick` |
|
|
65
|
+
| `@custom-event="fn"` | `attrs.onCustomEvent` |
|
|
66
|
+
| `@update:modelValue="fn"` | `attrs['onUpdate:modelValue']` |
|
|
67
|
+
|
|
68
|
+
## `useAttrs()` Is Not Reactive
|
|
69
|
+
|
|
70
|
+
`useAttrs()` always reflects the latest values, but it is intentionally not reactive for watcher tracking.
|
|
71
|
+
|
|
72
|
+
**BAD:**
|
|
73
|
+
```vue
|
|
74
|
+
<script setup>
|
|
75
|
+
import { watch, watchEffect, useAttrs } from 'vue'
|
|
76
|
+
|
|
77
|
+
const attrs = useAttrs()
|
|
78
|
+
|
|
79
|
+
watch(
|
|
80
|
+
() => attrs.someAttr,
|
|
81
|
+
(newValue) => {
|
|
82
|
+
console.log('Changed:', newValue) // Never runs on attr changes
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
watchEffect(() => {
|
|
87
|
+
console.log(attrs.class) // Runs on setup, not on attr updates
|
|
88
|
+
})
|
|
89
|
+
</script>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**GOOD:**
|
|
93
|
+
```vue
|
|
94
|
+
<script setup>
|
|
95
|
+
import { onUpdated, useAttrs } from 'vue'
|
|
96
|
+
|
|
97
|
+
const attrs = useAttrs()
|
|
98
|
+
|
|
99
|
+
onUpdated(() => {
|
|
100
|
+
console.log('Latest attrs:', attrs)
|
|
101
|
+
})
|
|
102
|
+
</script>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**GOOD:**
|
|
106
|
+
```vue
|
|
107
|
+
<script setup>
|
|
108
|
+
import { watch } from 'vue'
|
|
109
|
+
|
|
110
|
+
const props = defineProps({
|
|
111
|
+
someAttr: String
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
watch(
|
|
115
|
+
() => props.someAttr,
|
|
116
|
+
(newValue) => {
|
|
117
|
+
console.log('Changed:', newValue)
|
|
118
|
+
}
|
|
119
|
+
)
|
|
120
|
+
</script>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Common Patterns
|
|
124
|
+
|
|
125
|
+
### Check for optional attrs safely
|
|
126
|
+
|
|
127
|
+
```vue
|
|
128
|
+
<script setup>
|
|
129
|
+
import { computed, useAttrs } from 'vue'
|
|
130
|
+
|
|
131
|
+
const attrs = useAttrs()
|
|
132
|
+
|
|
133
|
+
const hasTestId = computed(() => 'data-testid' in attrs)
|
|
134
|
+
const ariaLabel = computed(() => attrs['aria-label'] ?? 'Default label')
|
|
135
|
+
</script>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Forward listeners after internal logic
|
|
139
|
+
|
|
140
|
+
```vue
|
|
141
|
+
<script setup>
|
|
142
|
+
import { useAttrs } from 'vue'
|
|
143
|
+
|
|
144
|
+
defineOptions({ inheritAttrs: false })
|
|
145
|
+
|
|
146
|
+
const attrs = useAttrs()
|
|
147
|
+
|
|
148
|
+
function handleClick(event) {
|
|
149
|
+
console.log('Internal handling first')
|
|
150
|
+
attrs.onClick?.(event)
|
|
151
|
+
}
|
|
152
|
+
</script>
|
|
153
|
+
|
|
154
|
+
<template>
|
|
155
|
+
<button @click="handleClick">
|
|
156
|
+
<slot />
|
|
157
|
+
</button>
|
|
158
|
+
</template>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## TypeScript Notes
|
|
162
|
+
|
|
163
|
+
`useAttrs()` is typed as `Record<string, unknown>`, so cast individual keys when needed.
|
|
164
|
+
|
|
165
|
+
```vue
|
|
166
|
+
<script setup lang="ts">
|
|
167
|
+
import { useAttrs } from 'vue'
|
|
168
|
+
|
|
169
|
+
const attrs = useAttrs()
|
|
170
|
+
|
|
171
|
+
const testId = attrs['data-testid'] as string | undefined
|
|
172
|
+
const onClick = attrs.onClick as ((event: MouseEvent) => void) | undefined
|
|
173
|
+
</script>
|
|
174
|
+
```
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: KeepAlive Component Best Practices
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: KeepAlive caches component instances; misuse causes stale data, memory growth, or unexpected lifecycle behavior
|
|
5
|
+
type: best-practice
|
|
6
|
+
tags: [vue3, keepalive, cache, performance, router, dynamic-components]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# KeepAlive Component Best Practices
|
|
10
|
+
|
|
11
|
+
**Impact: HIGH** - `<KeepAlive>` caches component instances instead of destroying them. Use it to preserve state across switches, but manage cache size and freshness explicitly to avoid memory growth or stale UI.
|
|
12
|
+
|
|
13
|
+
## Task List
|
|
14
|
+
|
|
15
|
+
- Use KeepAlive only where state preservation improves UX
|
|
16
|
+
- Set a reasonable `max` to cap cache size
|
|
17
|
+
- Declare component names for include/exclude matching
|
|
18
|
+
- Use `onActivated`/`onDeactivated` for cache-aware logic
|
|
19
|
+
- Decide how and when cached views refresh their data
|
|
20
|
+
- Avoid caching memory-heavy or security-sensitive views
|
|
21
|
+
|
|
22
|
+
## When to Use KeepAlive
|
|
23
|
+
|
|
24
|
+
Use KeepAlive when switching between views where state should persist (tabs, multi-step forms, dashboards). Avoid it when each visit should start fresh.
|
|
25
|
+
|
|
26
|
+
**BAD:**
|
|
27
|
+
```vue
|
|
28
|
+
<template>
|
|
29
|
+
<!-- State resets on every switch -->
|
|
30
|
+
<component :is="currentTab" />
|
|
31
|
+
</template>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**GOOD:**
|
|
35
|
+
```vue
|
|
36
|
+
<template>
|
|
37
|
+
<!-- State preserved between switches -->
|
|
38
|
+
<KeepAlive>
|
|
39
|
+
<component :is="currentTab" />
|
|
40
|
+
</KeepAlive>
|
|
41
|
+
</template>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## When NOT to Use KeepAlive
|
|
45
|
+
|
|
46
|
+
- Search or filter pages where users expect fresh results
|
|
47
|
+
- Memory-heavy components (maps, large tables, media players)
|
|
48
|
+
- Sensitive flows where data must be cleared on exit
|
|
49
|
+
- Components with heavy background activity you cannot pause
|
|
50
|
+
|
|
51
|
+
## Limit and Control the Cache
|
|
52
|
+
|
|
53
|
+
Always cap cache size with `max` and restrict caching to specific components when possible.
|
|
54
|
+
|
|
55
|
+
```vue
|
|
56
|
+
<template>
|
|
57
|
+
<KeepAlive :max="5" include="Dashboard,Settings">
|
|
58
|
+
<component :is="currentView" />
|
|
59
|
+
</KeepAlive>
|
|
60
|
+
</template>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Ensure Component Names Match include/exclude
|
|
64
|
+
|
|
65
|
+
`include` and `exclude` match the component `name` option. Explicitly set names for reliable caching.
|
|
66
|
+
|
|
67
|
+
```vue
|
|
68
|
+
<!-- TabA.vue -->
|
|
69
|
+
<script setup>
|
|
70
|
+
defineOptions({ name: 'TabA' })
|
|
71
|
+
</script>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```vue
|
|
75
|
+
<template>
|
|
76
|
+
<KeepAlive include="TabA,TabB">
|
|
77
|
+
<component :is="currentTab" />
|
|
78
|
+
</KeepAlive>
|
|
79
|
+
</template>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Cache Invalidation Strategies
|
|
83
|
+
|
|
84
|
+
Vue 3 has no direct API to remove a specific cached instance. Use keys or dynamic include/exclude to force refreshes.
|
|
85
|
+
|
|
86
|
+
```vue
|
|
87
|
+
<script setup>
|
|
88
|
+
import { ref, reactive } from 'vue'
|
|
89
|
+
|
|
90
|
+
const currentView = ref('Dashboard')
|
|
91
|
+
const viewKeys = reactive({ Dashboard: 0, Settings: 0 })
|
|
92
|
+
|
|
93
|
+
function invalidateCache(view) {
|
|
94
|
+
viewKeys[view]++
|
|
95
|
+
}
|
|
96
|
+
</script>
|
|
97
|
+
|
|
98
|
+
<template>
|
|
99
|
+
<KeepAlive>
|
|
100
|
+
<component :is="currentView" :key="`${currentView}-${viewKeys[currentView]}`" />
|
|
101
|
+
</KeepAlive>
|
|
102
|
+
</template>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Lifecycle Hooks for Cached Components
|
|
106
|
+
|
|
107
|
+
Cached components are not destroyed on switch. Use activation hooks for refresh and cleanup.
|
|
108
|
+
|
|
109
|
+
```vue
|
|
110
|
+
<script setup>
|
|
111
|
+
import { onActivated, onDeactivated } from 'vue'
|
|
112
|
+
|
|
113
|
+
onActivated(() => {
|
|
114
|
+
refreshData()
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
onDeactivated(() => {
|
|
118
|
+
pauseTimers()
|
|
119
|
+
})
|
|
120
|
+
</script>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Router Caching and Freshness
|
|
124
|
+
|
|
125
|
+
Decide whether navigation should show cached state or a fresh view. A common pattern is to key by route when params change.
|
|
126
|
+
|
|
127
|
+
```vue
|
|
128
|
+
<template>
|
|
129
|
+
<router-view v-slot="{ Component, route }">
|
|
130
|
+
<KeepAlive>
|
|
131
|
+
<component :is="Component" :key="route.fullPath" />
|
|
132
|
+
</KeepAlive>
|
|
133
|
+
</router-view>
|
|
134
|
+
</template>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
If you want cache reuse but fresh data, refresh in `onActivated` and compare query/params before fetching.
|