base_ui/COMPOSITION_API.md
2025-03-18 16:02:36 +03:30

289 lines
6.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 dont 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()
})