Comprehensive Vue 3 Cheat Sheet: Mastering the Composition API
Master Vue 3 with this in-depth guide to the Composition API. Learn advanced syntax, best practices, and powerful features to elevate your Vue development skills.
Comprehensive Vue 3 Cheat Sheet: Mastering the Composition API
Vue 3 introduces the powerful Composition API, revolutionizing how we build and structure Vue applications. This comprehensive guide will take you through the essential features, advanced techniques, and best practices for leveraging Vue 3 and the Composition API in your projects.
Why Vue 3 and the Composition API?
Before we dive into the specifics, it's crucial to understand why Vue 3 and the Composition API are game-changers in the world of frontend development:
- Improved code organization: The Composition API allows for better grouping of logical concerns, making your code more readable and maintainable.
- Enhanced reusability: With composition functions, you can easily extract and reuse logic across components.
- TypeScript integration: Vue 3 is built with TypeScript, offering improved type inference and a better developer experience for TypeScript users.
- Performance improvements: Vue 3's reactivity system and virtual DOM have been optimized for better performance.
Now, let's explore the key features and syntax of Vue 3 with the Composition API.
Setting up with Vite
To get started with Vue 3, we'll use Vite, a build tool that offers a faster and leaner development experience. Here's why Vite is the preferred choice:
- Faster development server: Vite leverages native ES modules for instant server start.
- Optimized builds: It uses Rollup for efficient production builds.
- Hot Module Replacement (HMR): Vite provides lightning-fast updates during development.
Let's set up a new Vue 3 project using Vite:
npm init vite@latest my-vue3-project --template vue
cd my-vue3-project
npm install
npm run dev
This command sequence creates a new Vue 3 project, installs dependencies, and starts the development server. The --template vue
flag ensures we're using the Vue 3 template with Vite.
Single File Components with <script setup>
Vue 3 introduces the <script setup>
syntax, a game-changer for writing more concise and efficient components. Here's why you should use it:
- Less boilerplate: No need to explicitly define and return component options.
- Better performance: The compiler can better optimize the component at build time.
- Improved TypeScript integration: TypeScript inference works seamlessly with
<script setup>
.
Let's look at an example:
<template>
<div>{{ message }}</div>
</template>
<script setup>
import { ref } from 'vue';
const message = ref('Hello Vue 3!');
</script>
<style scoped>
div {
color: #41b883;
font-weight: bold;
}
</style>
In this example, we're using ref
to create a reactive reference. The message
variable is automatically exposed to the template without needing to be returned from a setup
function.
Reactive State and Refs
Understanding reactivity is crucial in Vue 3. The Composition API provides powerful tools for managing reactive state:
ref
Use ref
for creating reactive references to primitive values:
<template>
<button @click="increment">Count: {{ count }}</button>
</template>
<script setup>
import { ref } from 'vue';
const count = ref(0);
function increment() {
count.value++;
}
</script>
Why use ref
?
- It wraps primitive values in a reactive object.
- Access the value using
.value
in JavaScript (automatically unwrapped in templates). - Triggers re-renders when the value changes.
reactive
For more complex state, use reactive
:
<template>
<div>
<h2>{{ user.name }}</h2>
<p>Age: {{ user.age }}</p>
</div>
</template>
<script setup>
import { reactive } from 'vue';
const user = reactive({
name: 'John Doe',
age: 30
});
</script>
Why use reactive
?
- Creates a reactive proxy of the entire object.
- Properties can be accessed directly without
.value
. - Suitable for complex nested objects.
Computed Properties
Computed properties are essential for deriving values from your reactive state. They're cached based on their dependencies and only re-evaluate when needed.
<template>
<div>
<input v-model="firstName" placeholder="First Name">
<input v-model="lastName" placeholder="Last Name">
<p>Full Name: {{ fullName }}</p>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const firstName = ref('');
const lastName = ref('');
const fullName = computed(() => {
return firstName.value && lastName.value
? `${firstName.value} ${lastName.value}`
: 'Please enter a name';
});
</script>
Why use computed properties?
- Performance optimization: The result is cached until dependencies change.
- Declarative coding: Clearly express the relationship between state and derived values.
- Reactivity: Automatically update when dependencies change.
Watchers
Watchers allow you to observe changes in your reactive state and perform side effects accordingly.
<template>
<input v-model="searchQuery" placeholder="Search...">
<p>Results: {{ results.join(', ') }}</p>
</template>
<script setup>
import { ref, watch } from 'vue';
const searchQuery = ref('');
const results = ref([]);
watch(searchQuery, async (newQuery, oldQuery) => {
if (newQuery.trim()) {
// Simulating an API call
const response = await fetch(`https://api.example.com/search?q=${newQuery}`);
results.value = await response.json();
} else {
results.value = [];
}
}, { immediate: true });
</script>
Why use watchers?
- Reactive side effects: Perform actions based on state changes.
- Control over timing: Unlike computed properties, watchers give you control over when to run side effects.
- Access to previous values: Watchers provide both new and old values of the watched source.
Lifecycle Hooks
Vue 3's Composition API provides a new way to work with lifecycle hooks:
<template>
<div>{{ message }}</div>
</template>
<script setup>
import { ref, onMounted, onUpdated, onUnmounted } from 'vue';
const message = ref('Hello');
onMounted(() => {
console.log('Component is mounted');
});
onUpdated(() => {
console.log('Component is updated');
});
onUnmounted(() => {
console.log('Component is unmounted');
});
</script>
Why use lifecycle hooks?
- Timing control: Execute code at specific points in a component's lifecycle.
- Setup and cleanup: Ideal for setting up and cleaning up side effects.
- Integration with external libraries: Use hooks to initialize or destroy third-party plugins.
Provide / Inject
For passing data deeply through component trees without prop drilling, use provide
and inject
:
<template>
<slot></slot>
</template>
<script setup>
import { ref, provide } from 'vue';
const theme = ref('light');
provide('theme', theme);
function toggleTheme() {
theme.value = theme.value === 'light' ? 'dark' : 'light';
}
provide('toggleTheme', toggleTheme);
</script>
<template>
<button :class="theme" @click="toggleTheme">
Toggle Theme
</button>
</template>
<script setup>
import { inject } from 'vue';
const theme = inject('theme');
const toggleTheme = inject('toggleTheme');
</script>
Why use provide/inject?
- Avoid prop drilling: Pass data through multiple component layers efficiently.
- Centralize state management: Useful for app-wide state like themes or user authentication.
- Loose coupling: Child components don't need to know where the data comes from.
Composables
Composables are a powerful feature of the Composition API, allowing you to extract and reuse stateful logic across components:
import { ref, onMounted, onUnmounted } from 'vue';
export function useMousePosition() {
const x = ref(0);
const y = ref(0);
function update(event) {
x.value = event.pageX;
y.value = event.pageY;
}
onMounted(() => window.addEventListener('mousemove', update));
onUnmounted(() => window.removeEventListener('mousemove', update));
return { x, y };
}
Using the composable in a component:
<template>
<div>Mouse position: {{ x }}, {{ y }}</div>
</template>
<script setup>
import { useMousePosition } from './useMousePosition';
const { x, y } = useMousePosition();
</script>
Why use composables?
- Code reusability: Extract and share complex logic across components.
- Separation of concerns: Keep components focused on presentation, move logic to composables.
- Testability: Easier to unit test logic in isolation.
Conclusion
Vue 3 and the Composition API offer a powerful and flexible way to build modern web applications. By mastering these concepts, you'll be able to create more maintainable, performant, and scalable Vue applications.
Remember to always consider the specific needs of your project when deciding which features to use. The Composition API provides great flexibility, but it's important to use it judiciously to keep your code clean and understandable.
For more advanced topics and best practices, check out the official Vue 3 documentation:
Vue 3 Official DocumentationHappy coding with Vue 3!