Getting Started with the Basics of Vue 3 Composition API
Alongside introducing a brand new reactivity system, Vue 3 also launched the Composition API as an important complement to the Options API. The Composition API allows developers to separate related logic from component templates and combine it through functions. This design pattern is particularly suitable for scenarios requiring complex state management or specific business logic.
The traditional Options API requires us to scatter data, methods, lifecycle hooks, and properties across different options such as data, methods, lifecycle, and computed. When components become complex, this structure leads to code that is difficult to read and maintain because related logic is scattered in different places. In contrast, the Composition API gathers all logic related to a specific feature together by introducing the setup() function. This not only improves code readability but also enhances code reusability.
For example, in an e-commerce application, if we need to handle user shopping carts, order status, and payment methods, the Options API might require extensive nested logic or additional helper functions. The Composition API allows us to define a useCart composable function containing all logic related to the cart, such as adding items and calculating totals. This modular design makes the logic clearer, easier to test, and maintainable.
Basic Syntax Structure and the setup Function
The first step in using the Composition API in Vue 3 is understanding the basic structure of the setup() function. setup() is a function that accepts two parameters: the first parameter is typically used to return properties, methods, and computed properties exposed by the component; the second parameter (optional) allows access to the Vue instance but is rarely needed in most cases.
import { ref, computed } from 'vue'
export default {
setup(props, ctx) {
const count = ref(0)
const doubled = computed(() => count.value * 2)
return {
count,
doubled,
increment() {
count.value++
}
}
}
}
In the above example, ref is used to create reactive variables, while computed is used to create computed properties based on other reactive data. The returned object contains the data and methods that the component needs to expose for use in the template.
Common Composables and Lifecycle Management
Vue 3 provides a series of predefined composables to handle common scenarios such as form validation, route navigation, and error boundaries. These functions simplify the development process and improve code efficiency.
Reactive State Management
ref and reactive are the most commonly used reactive tools in the Composition API. ref is suitable for primitive data types, while reactive is better suited for objects or arrays.
const user = reactive({
name: 'Alice',
age: 25
})
const isAdult = computed(() => user.age >= 18)
Lifecycle Hooks
The Composition API also supports custom lifecycle hooks implemented through functions like onMounted and onUnmounted.
import { onMounted, onUnmounted } from 'vue'
export default {
setup() {
let intervalId
const startTimer = () => {
intervalId = setInterval(() => {
console.log('Timer tick')
}, 1000)
}
onMounted(startTimer)
onUnmounted(() => clearInterval(intervalId))
return {}
}
}
Practical Application Example
To demonstrate the usage of the Composition API more intuitively, let's look at a complete user login form example. In this scenario, we will encapsulate form validation, error handling, and submission logic within a useForm composable function.
import { ref, reactive, computed } from 'vue'
import { useRouter } from 'vue-router'
export function useForm() {
const router = useRouter()
const formState = reactive({
email: '',
password: ''
})
const errors = reactive({
email: '',
password: ''
})
const isValid = computed(() => {
return !errors.email && !errors.password
})
const validateEmail = () => {
if (!formState.email.includes('@')) {
errors.email = 'Please enter a valid email address'
return false
}
errors.email = ''
return true
}
const validatePassword = () => {
if (formState.password.length < 6) {
errors.password = 'Password length must be at least 6 characters'
return false
}
errors.password = ''
return true
}
const handleSubmit = async () => {
if (!validateEmail() || !validatePassword()) {
return
}
try {
// Simulate API request
await new Promise(resolve => setTimeout(resolve, 1000))
router.push('/dashboard')
} catch (error) {
console.error('Login failed:', error)
}
}
return {
formState,
errors,
isValid,
validateEmail,
validatePassword,
handleSubmit
}
}
Usage of this composable in the template:
<template>
<div class="login-form">
<input v-model="formState.email" @blur="validateEmail" placeholder="Email" />
<span v-if="errors.email" class="error">{{ errors.email }}</span>
<input v-model="formState.password" @blur="validatePassword" type="password" placeholder="Password" />
<span v-if="errors.password" class="error">{{ errors.password }}</span>
<button :disabled="!isValid" @click="handleSubmit">Login</button>
</div>
</template>
<script setup>
const { formState, errors, isValid, validateEmail, validatePassword, handleSubmit } = useForm()
</script>
Summary and Best Practices
The Composition API provides Vue 3 developers with more flexible and powerful tools to build complex applications. Through composables, we can modularize logic, improving code maintainability and testability. In actual development, it is recommended to follow these best practices:
- Prioritize using predefined composables (such as
useRouter,useFetch) to handle common scenarios. - Keep each composable's responsibility single, focusing on specific business logic.
- Fully utilize the reactive system to ensure data flows are clear and visible.
- In large projects, consider extracting commonly used composables into independent libraries or plugins for team reuse.
By mastering the Composition API, developers can better address the challenges of modern frontend development and build high-performance, highly maintainable Vue applications.