The Composition API in Vue 3 is a new way to organize and reuse logic in Vue components. It was introduced to
address some limitations of the Options API (used in Vue 2), especially when dealing with large or complex
components where logic can become scattered and hard to manage.
The Composition API is a set of APIs (e.g., setup(), ref, reactive, computed, watch, etc.) that allow
developers to compose component logic more flexibly and cleanly, especially when logic is reused across
components.
Key Concepts
- The
**setup()** function
The heart of the Composition API. It's called before the component is created, and it's the place where you
declare reactive state, computed properties, methods, and lifecycle hooks.
<template>
<button @click="increment">Count is: {{ count }}</button>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
</script>
ref() creates a reactive reference to a primitive value.
count.value is how you access/update the value inside a ref.
- Reactive State:
**ref()** and **reactive()**
ref()
- Used for primitive values.
- Wraps a value in a reactive object.
const message = ref('Hello');
message.value = 'Hi';
reactive()
- Used for objects.
- Deeply reactive, making every property reactive.
const user = reactive({ name: 'Alice', age: 25 });
user.age++;
- Computed Properties
Creates values that automatically update when dependencies change.
import { ref, computed } from 'vue';
setup() {
const firstName = ref('John');
const lastName = ref('Doe');
const fullName = computed(() => `${firstName.value} ${lastName.value}`);
return { fullName };
}
- Watchers
Both watch() and watchEffect() are used to run side effects when data changes:
watch(count, (newVal, oldVal) => {
console.log('Count changed:', newVal);
});
watchEffect(() => {
console.log('Count is now', count.value);
});
- Lifecycle Hooks
Composition API uses new lifecycle hooks imported from Vue.
import { onMounted, onUnmounted } from 'vue';
onMounted(() => {
console.log('Component is mounted');
});
onUnmounted(() => {
console.log('Component is unmounted');
});
- Reusable Logic with Composables
You can encapsulate logic in composable functions and reuse across components:
Example: Reuse logic of counter using useCounter.js
import { ref } from 'vue';
export function useCounter(initialValue = 0) {
const count = ref(initialValue);
const increment = () => count.value++;
const decrement = () => count.value--;
const reset = () => count.value = initialValue;
return { count, increment, decrement, reset };
}
Using it in a component
<script setup>
import { useCounter } from '@/composables/useCounter';
const { count, increment, decrement, reset } = useCounter(5);
</script>
<template>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="reset">Reset</button>
</template>