ERP/.shared/ui-ux-pro-max/data/stacks/vue.csv
2026-01-03 19:18:40 +08:00

11 KiB

1NoCategoryGuidelineDescriptionDoDon'tCode GoodCode BadSeverityDocs URL
21CompositionUse Composition API for new projectsComposition API offers better TypeScript support and logic reuse<script setup> for componentsOptions API for new projects<script setup>export default { data() }Mediumhttps://vuejs.org/guide/extras/composition-api-faq.html
32CompositionUse script setup syntaxCleaner syntax with automatic exports<script setup> with definePropssetup() function manually<script setup><script> setup() { return {} }Lowhttps://vuejs.org/api/sfc-script-setup.html
43ReactivityUse ref for primitivesref() for primitive values that need reactivityref() for strings numbers booleansreactive() for primitivesconst count = ref(0)const count = reactive(0)Mediumhttps://vuejs.org/guide/essentials/reactivity-fundamentals.html
54ReactivityUse reactive for objectsreactive() for complex objects and arraysreactive() for objects with multiple propertiesref() for complex objectsconst state = reactive({ user: null })const state = ref({ user: null })Medium
65ReactivityAccess ref values with .valueRemember .value in script unwrap in templateUse .value in scriptForget .value in scriptcount.value++count++ (in script)High
76ReactivityUse computed for derived stateComputed properties cache and update automaticallycomputed() for derived valuesMethods for derived valuesconst doubled = computed(() => count.value * 2)const doubled = () => count.value * 2Mediumhttps://vuejs.org/guide/essentials/computed.html
87ReactivityUse shallowRef for large objectsAvoid deep reactivity for performanceshallowRef for large data structuresref for large nested objectsconst bigData = shallowRef(largeObject)const bigData = ref(largeObject)Mediumhttps://vuejs.org/api/reactivity-advanced.html#shallowref
98WatchersUse watchEffect for simple casesAuto-tracks dependencieswatchEffect for simple reactive effectswatch with explicit deps when not neededwatchEffect(() => console.log(count.value))watch(count, (val) => console.log(val))Lowhttps://vuejs.org/guide/essentials/watchers.html
109WatchersUse watch for specific sourcesExplicit control over what to watchwatch with specific refswatchEffect for complex conditional logicwatch(userId, fetchUser)watchEffect with conditionalsMedium
1110WatchersClean up side effectsReturn cleanup function in watchersReturn cleanup in watchEffectLeave subscriptions openwatchEffect((onCleanup) => { onCleanup(unsub) })watchEffect without cleanupHigh
1211PropsDefine props with definePropsType-safe prop definitionsdefineProps with TypeScriptProps without typesdefineProps<{ msg: string }>()defineProps(['msg'])Mediumhttps://vuejs.org/guide/typescript/composition-api.html#typing-component-props
1312PropsUse withDefaults for default valuesProvide defaults for optional propswithDefaults with definePropsDefaults in destructuringwithDefaults(defineProps<Props>(), { count: 0 })const { count = 0 } = defineProps()Medium
1413PropsAvoid mutating propsProps should be read-onlyEmit events to parent for changesDirect prop mutationemit('update:modelValue', newVal)props.modelValue = newValHigh
1514EmitsDefine emits with defineEmitsType-safe event emissionsdefineEmits with typesEmit without definitiondefineEmits<{ change: [id: number] }>()emit('change', id) without defineMediumhttps://vuejs.org/guide/typescript/composition-api.html#typing-component-emits
1615EmitsUse v-model for two-way bindingSimplified parent-child data flowv-model with modelValue prop:value + @input manually<Child v-model="value"/><Child :value="value" @input="value = $event"/>Lowhttps://vuejs.org/guide/components/v-model.html
1716LifecycleUse onMounted for DOM accessDOM is ready in onMountedonMounted for DOM operationsAccess DOM in setup directlyonMounted(() => el.value.focus())el.value.focus() in setupHighhttps://vuejs.org/api/composition-api-lifecycle.html
1817LifecycleClean up in onUnmountedRemove listeners and subscriptionsonUnmounted for cleanupLeave listeners attachedonUnmounted(() => window.removeEventListener())No cleanup on unmountHigh
1918LifecycleAvoid onBeforeMount for dataUse onMounted or setup for data fetchingFetch in onMounted or setupFetch in onBeforeMountonMounted(async () => await fetchData())onBeforeMount(async () => await fetchData())Low
2019ComponentsUse single-file componentsKeep template script style together.vue files for componentsSeparate template/script filesComponent.vue with all partsComponent.js + Component.htmlLow
2120ComponentsUse PascalCase for componentsConsistent component namingPascalCase in imports and templateskebab-case in script<MyComponent/><my-component/>Lowhttps://vuejs.org/style-guide/rules-strongly-recommended.html
2221ComponentsPrefer composition over mixinsComposables replace mixinsComposables for shared logicMixins for code reuseconst { data } = useApi()mixins: [apiMixin]Medium
2322ComposablesName composables with use prefixConvention for composable functionsuseFetch useAuth useFormgetData or fetchApiexport function useFetch()export function fetchData()Mediumhttps://vuejs.org/guide/reusability/composables.html
2423ComposablesReturn refs from composablesMaintain reactivity when destructuringReturn ref valuesReturn reactive objects that lose reactivityreturn { data: ref(null) }return reactive({ data: null })Medium
2524ComposablesAccept ref or value paramsUse toValue for flexible inputstoValue() or unref() for paramsOnly accept ref or only valueconst val = toValue(maybeRef)const val = maybeRef.valueLowhttps://vuejs.org/api/reactivity-utilities.html#tovalue
2625TemplatesUse v-bind shorthandCleaner template syntax:prop instead of v-bind:propFull v-bind syntax<div :class="cls"><div v-bind:class="cls">Low
2726TemplatesUse v-on shorthandCleaner event binding@event instead of v-on:eventFull v-on syntax<button @click="handler"><button v-on:click="handler">Low
2827TemplatesAvoid v-if with v-forv-if has higher priority causes issuesWrap in template or computed filterv-if on same element as v-for<template v-for><div v-if><div v-for v-if>Highhttps://vuejs.org/style-guide/rules-essential.html#avoid-v-if-with-v-for
2928TemplatesUse key with v-forProper list rendering and updatesUnique key for each itemIndex as key for dynamic listsv-for="item in items" :key="item.id"v-for="(item, i) in items" :key="i"High
3029StateUse Pinia for global stateOfficial state management for Vue 3Pinia stores for shared stateVuex for new projectsconst store = useCounterStore()Vuex with mutationsMediumhttps://pinia.vuejs.org/
3130StateDefine stores with defineStoreComposition API style storesSetup stores with defineStoreOptions stores for complex statedefineStore('counter', () => {})defineStore('counter', { state })Low
3231StateUse storeToRefs for destructuringMaintain reactivity when destructuringstoreToRefs(store)Direct destructuringconst { count } = storeToRefs(store)const { count } = storeHighhttps://pinia.vuejs.org/core-concepts/#destructuring-from-a-store
3332RoutingUse useRouter and useRouteComposition API router accessuseRouter() useRoute() in setupthis.$router this.$routeconst router = useRouter()this.$router.push()Mediumhttps://router.vuejs.org/guide/advanced/composition-api.html
3433RoutingLazy load route componentsCode splitting for routes() => import() for componentsStatic imports for all routescomponent: () => import('./Page.vue')component: PageMediumhttps://router.vuejs.org/guide/advanced/lazy-loading.html
3534RoutingUse navigation guardsProtect routes and handle redirectsbeforeEach for auth checksCheck auth in each componentrouter.beforeEach((to) => {})Check auth in onMountedMedium
3635PerformanceUse v-once for static contentSkip re-renders for static elementsv-once on never-changing contentv-once on dynamic content<div v-once>{{ staticText }}</div><div v-once>{{ dynamicText }}</div>Lowhttps://vuejs.org/api/built-in-directives.html#v-once
3736PerformanceUse v-memo for expensive listsMemoize list itemsv-memo with dependency arrayRe-render entire list always<div v-for v-memo="[item.id]"><div v-for> without memoMediumhttps://vuejs.org/api/built-in-directives.html#v-memo
3837PerformanceUse shallowReactive for flat objectsAvoid deep reactivity overheadshallowReactive for flat statereactive for simple objectsshallowReactive({ count: 0 })reactive({ count: 0 })Low
3938PerformanceUse defineAsyncComponentLazy load heavy componentsdefineAsyncComponent for modals dialogsImport all components eagerlydefineAsyncComponent(() => import())import HeavyComponent fromMediumhttps://vuejs.org/guide/components/async.html
4039TypeScriptUse generic componentsType-safe reusable componentsGeneric with defineComponentAny types in components<script setup lang="ts" generic="T"><script setup> without typesMediumhttps://vuejs.org/guide/typescript/composition-api.html
4140TypeScriptType template refsProper typing for DOM refsref<HTMLInputElement>(null)ref(null) without typeconst input = ref<HTMLInputElement>(null)const input = ref(null)Medium
4241TypeScriptUse PropType for complex propsType complex prop typesPropType<User> for object propsObject without typetype: Object as PropType<User>type: ObjectMedium
4342TestingUse Vue Test UtilsOfficial testing librarymount shallowMount for componentsManual DOM testingimport { mount } from '@vue/test-utils'document.createElementMediumhttps://test-utils.vuejs.org/
4443TestingTest component behaviorFocus on inputs and outputsTest props emit and rendered outputTest internal implementationexpect(wrapper.text()).toContain()expect(wrapper.vm.internalState)Medium
4544FormsUse v-model modifiersBuilt-in input handling.lazy .number .trim modifiersManual input parsing<input v-model.number="age"><input v-model="age"> then parseLowhttps://vuejs.org/guide/essentials/forms.html#modifiers
4645FormsUse VeeValidate or FormKitForm validation librariesVeeValidate for complex formsManual validation logicuseField useForm from vee-validateCustom validation in each inputMedium
4746AccessibilityUse semantic elementsProper HTML elements in templatesbutton nav main for purposediv for everything<button @click><div @click>High
4847AccessibilityBind aria attributes dynamicallyKeep ARIA in sync with state:aria-expanded="isOpen"Static ARIA values:aria-expanded="menuOpen"aria-expanded="true"Medium
4948SSRUse Nuxt for SSRFull-featured SSR frameworkNuxt 3 for SSR appsManual SSR setupnpx nuxi init my-appCustom SSR configurationMediumhttps://nuxt.com/
5049SSRHandle hydration mismatchesClient/server content must matchClientOnly for browser-only contentDifferent content server/client<ClientOnly><BrowserWidget/></ClientOnly><div>{{ Date.now() }}</div>High