Composables help you share and reuse code easily in Vue. They keep your code clean and organized.
Composables for reusable logic in Vue
Introduction
Syntax
Vue
import { ref } from 'vue'; export function useExample() { const state = ref(0); function increment() { state.value++; } return { state, increment }; }
Composables are regular JavaScript functions that use Vue's reactive features.
They start with 'use' by convention to show they provide reusable logic.
Examples
Vue
import { ref } from 'vue'; export function useCounter() { const count = ref(0); function increase() { count.value++; } return { count, increase }; }
Vue
import { ref, onMounted, onUnmounted } from 'vue'; export function useWindowWidth() { const width = ref(window.innerWidth); function updateWidth() { width.value = window.innerWidth; } onMounted(() => { window.addEventListener('resize', updateWidth); }); onUnmounted(() => { window.removeEventListener('resize', updateWidth); }); return { width }; }
Sample Program
This Vue component uses a composable useToggle to manage a toggle state. The button text changes between ON and OFF when clicked. The aria-pressed attribute improves accessibility by indicating the toggle state to screen readers.
Vue
<script setup> import { ref } from 'vue'; function useToggle(initial = false) { const isOn = ref(initial); function toggle() { isOn.value = !isOn.value; } return { isOn, toggle }; } const { isOn, toggle } = useToggle(); </script> <template> <button @click="toggle" :aria-pressed="isOn"> {{ isOn ? 'ON' : 'OFF' }} </button> </template>
Important Notes
Always name composables starting with use to keep code clear.
Composables can use Vue's reactive features like ref and reactive.
Use composables to keep components focused on UI, not logic.
Summary
Composables let you reuse logic easily across Vue components.
They are simple functions using Vue's reactive tools.
Use composables to keep your code clean and maintainable.
Practice
1. What is the main purpose of a
composable in Vue?easy
Solution
Step 1: Understand composables role
Composables are functions that encapsulate reactive logic to be reused.Step 2: Identify main purpose
They help share logic like state or effects across components without duplication.Final Answer:
To reuse reactive logic across multiple components -> Option AQuick Check:
Composable = reusable logic [OK]
Hint: Composables share logic, not styles or components [OK]
Common Mistakes:
- Confusing composables with CSS or templates
- Thinking composables register components
- Assuming composables create directives
2. Which of the following is the correct way to define a composable in Vue 3?
easy
Solution
Step 1: Check composable function syntax
A composable is a function that returns reactive state or methods.Step 2: Validate options
function useCounter() { const count = ref(0); return { count }; } defines a function returning a ref wrapped count, which is correct. const useCounter = new Vue({ data() { return { count: 0 } } }) wrongly uses Vue instance syntax. const useCounter = reactive({ count: 0 }) returns reactive object directly without function. function useCounter() { return reactive({ count: 0 }) } returns reactive but misses ref usage and best practice.Final Answer:
function useCounter() { const count = ref(0); return { count }; } -> Option DQuick Check:
Composable = function returning reactive state [OK]
Hint: Composable must be a function returning reactive data [OK]
Common Mistakes:
- Defining composables as Vue instances
- Returning reactive objects without a function
- Not using ref or reactive inside composables
3. Given this composable:
import { ref } from 'vue';
export function useToggle() {
const isOn = ref(false);
function toggle() { isOn.value = !isOn.value; }
return { isOn, toggle };
}What will be the value of isOn.value after calling toggle() twice starting from initial state?medium
Solution
Step 1: Analyze initial state and toggle function
Initially,isOn.valueis false. Each toggle flips it to the opposite.Step 2: Apply two toggles
First toggle: false -> true. Second toggle: true -> false.Final Answer:
false -> Option CQuick Check:
Two toggles flip false twice back to false [OK]
Hint: Toggle flips boolean; even toggles return original [OK]
Common Mistakes:
- Assuming toggle sets true always
- Forgetting to access .value of ref
- Confusing initial state with toggled state
4. What is wrong with this composable code?
import { ref } from 'vue';
export function useCount() {
const count = ref(0);
function increment() {
count++;
}
return { count, increment };
}medium
Solution
Step 1: Understand ref usage
Ref values are accessed and mutated via the.valueproperty.Step 2: Identify error in increment function
The code usescount++which tries to increment the ref object itself, not its value. It should becount.value++.Final Answer:
You cannot increment a ref directly with ++ operator -> Option BQuick Check:
Use count.value++ to update ref [OK]
Hint: Always use .value to read or write ref values [OK]
Common Mistakes:
- Incrementing ref without .value
- Confusing reactive and ref imports
- Thinking function name affects behavior
5. You want to create a composable that tracks window width and updates reactively on resize. Which approach correctly implements this?
hard
Solution
Step 1: Understand reactive window width tracking
We need a ref to hold width and update it on resize events.Step 2: Check event listener lifecycle management
function useWindowWidth() { const width = ref(window.innerWidth); onMounted(() => { window.addEventListener('resize', () => { width.value = window.innerWidth; }); }); onUnmounted(() => { window.removeEventListener('resize', () => { width.value = window.innerWidth; }); }); return { width }; } correctly adds listener on mount and removes it on unmount to avoid leaks. function useWindowWidth() { const width = ref(window.innerWidth); window.addEventListener('resize', () => { width.value = window.innerWidth; }); return { width }; } adds listener immediately without cleanup. function useWindowWidth() { const width = reactive({ value: window.innerWidth }); window.onresize = () => { width.value = window.innerWidth; }; return width; } uses reactive incorrectly and overwrites window.onresize. function useWindowWidth() { const width = ref(0); window.addEventListener('resize', () => { width = window.innerWidth; }); return { width }; } tries to assign to ref variable directly, which is invalid.Final Answer:
function useWindowWidth() { const width = ref(window.innerWidth); onMounted(() => { window.addEventListener('resize', () => { width.value = window.innerWidth; }); }); onUnmounted(() => { window.removeEventListener('resize', () => { width.value = window.innerWidth; }); }); return { width }; } -> Option AQuick Check:
Manage listeners with lifecycle hooks [OK]
Hint: Add and remove listeners inside lifecycle hooks [OK]
Common Mistakes:
- Not removing event listeners causing memory leaks
- Assigning directly to ref variable instead of .value
- Overwriting window.onresize instead of adding listener
Recommended
Ready to prove it?
Pass the test and this pattern moves unknown
10 questions ~5 mineasy hard
