1. Organize Your Code into Logical Sections Structure your component script into clear sections to improve readability. A common approach is to group related logic together. Example Structure: <script setup> // 1. Imports import { ref, computed, onMounted } from 'vue' import { useRouter } from 'vue-router' // 2. Reactive State const count = ref(0) const name = ref('') // 3. Computed Properties const doubledCount = computed(() => count.value * 2) // 4. Functions / Methods function increment() { count.value++ } // 5. Lifecycle Hooks onMounted(() => { console.log('Component mounted') }) // 6. Watchers watch(count, (newValue, oldValue) => { console.log(`Count changed from ${oldValue} to ${newValue}`) }) </script> --- 2. Use script setup Syntax The <script setup> syntax is the recommended way to write Composition API components. It provides a more concise and intuitive syntax. Example: <script setup> const message = ref('Hello, Vue 3!') </script> <template> <p>{{ message }}</p> </template> --- 3. Use Descriptive Variable and Function Names Choose meaningful names for variables, functions, and computed properties to make your code self-documenting. Example: // Bad const x = ref(0) // Good const userCount = ref(0) --- 4. Extract Reusable Logic into Composables Move reusable logic into composables (custom hooks) to keep your components clean and promote code reuse. Example Composable: // composables/useCounter.js import { ref } from 'vue' export function useCounter(initialValue = 0) { const count = ref(initialValue) function increment() { count.value++ } function reset() { count.value = initialValue } return { count, increment, reset, } } Usage in a Component: <script setup> import { useCounter } from '~/composables/useCounter' const { count, increment } = useCounter() </script> <template> <p>Count: {{ count }}</p> <button @click="increment">Increment</button> </template> --- 5. Use ref for Primitive Values and reactive for Objects - Use ref for primitive values (e.g., numbers, strings, booleans). - Use reactive for objects or arrays. Example: const count = ref(0) // Primitive value const user = reactive({ name: 'John', age: 30 }) // Object --- 6. Use Computed Properties for Derived State Use computed to create reactive properties that depend on other state. This ensures the derived state is always up-to-date. Example: const firstName = ref('John') const lastName = ref('Doe') const fullName = computed(() => `${firstName.value} ${lastName.value}`) --- 7. Use Watchers Sparingly Watchers (watch and watchEffect) are powerful but can make your code harder to understand if overused. Prefer computed properties or event-driven updates where possible. Example: watch(count, (newValue, oldValue) => { console.log(`Count changed from ${oldValue} to ${newValue}`) }) --- 8. Group Related Logic Together Keep related reactive state, computed properties, and functions together to make your code easier to follow. Example: // User-related logic const user = reactive({ name: 'John', age: 30 }) const isAdult = computed(() => user.age >= 18) function updateUser(newName) { user.name = newName } ----------- 9. Use Lifecycle Hooks for Side Effects Use lifecycle hooks (onMounted, onUnmounted, etc.) for side effects like fetching data or setting up event listeners. Example: onMounted(() => { console.log('Component mounted') fetchData() }) onUnmounted(() => { console.log('Component unmounted') cleanup() }) ---------------- 10. Use TypeScript for Better Type Safety If your project uses TypeScript, leverage it to add type safety to your components. Example: <script setup lang="ts"> interface User { name: string age: number } const user = ref<User>({ name: 'John', age: 30 }) </script> -------------- 11. Keep Templates Clean Avoid putting too much logic in your template. Instead, move complex logic into the script or composables. Example: <template> <div> <p>{{ fullName }}</p> <button @click="increment">Increment</button> </div> </template> <script setup> const firstName = ref('John') const lastName = ref('Doe') const fullName = computed(() => `${firstName.value} ${lastName.value}`) function increment() { // Logic here } </script> ------------ 12. Use provide and inject for Prop Drilling Avoid prop drilling by using provide and inject to share state across deeply nested components. Example: // Parent component import { provide, ref } from 'vue' const theme = ref('dark') provide('theme', theme) // Child component import { inject } from 'vue' const theme = inject('theme') ----------------- 13. Use v-model for Two-Way Binding Use v-model to simplify two-way binding between parent and child components. Example: <!-- Parent component --> <template> <ChildComponent v-model:name="userName" /> </template> <script setup> const userName = ref('John') </script> <!-- Child component --> <template> <input :value="name" @input="$emit('update:name', $event.target.value)" /> </template> <script setup> defineProps(['name']) defineEmits(['update:name']) </script> ---------- 14. Use defineProps and defineEmits for TypeScript Support When using TypeScript, use defineProps and defineEmits to define props and emits with type safety. Example: <script setup lang="ts"> const props = defineProps<{ title: string count: number }>() const emit = defineEmits<{ (event: 'update:count', value: number): void }>() </script> ------------- 15. Use Scoped Styles Use scoped styles (<style scoped>) to ensure styles are component-specific and don’t leak into other components. Example: <style scoped> .button { background-color: blue; } </style> ------------------ 16. Use Environment Variables Use environment variables for configuration (e.g., API URLs) to keep your code flexible and secure. Example: const apiUrl = import.meta.env.VITE_API_URL ------------- 17. Write Unit Tests Write unit tests for your components and composables to ensure they work as expected. Example: import { render } from '@testing-library/vue' import MyComponent from '@/components/MyComponent.vue' test('renders correctly', () => { const { getByText } = render(MyComponent) expect(getByText('Hello, Vue 3!')).toBeInTheDocument() })