Building Reusable Logic with Vue 3 Composables
This challenge focuses on implementing Vue 3 composables in TypeScript. Composables are functions that encapsulate reusable stateful logic, making your Vue applications more modular, organized, and easier to test. You will create a custom composable to manage a simple counter with increment and decrement functionality.
Problem Description
Your task is to create a Vue 3 composable function, useCounter, written in TypeScript. This composable should manage a numerical counter and provide methods to increment, decrement, and reset the counter's value.
Key Requirements:
- Composable Function: Create a function named
useCounter. - State Management: The composable must manage a reactive
countvariable. - Methods: The composable should expose three functions:
increment(): Increases thecountby 1.decrement(): Decreases thecountby 1.reset(): Resets thecountto an initial value.
- Initial Value: The
useCountercomposable should accept an optionalinitialValueargument. If not provided, it should default to 0. - TypeScript: The entire implementation must be in TypeScript.
- Reactivity: The
countmust be reactive, meaning changes to it should automatically update any Vue components that use the composable.
Expected Behavior:
When useCounter is called within a Vue component:
- The returned
countshould be reactive. - Calling
increment()should increase the displayed count. - Calling
decrement()should decrease the displayed count. - Calling
reset()should set the count back to its initial value.
Edge Cases:
- Handling cases where
initialValueis not provided. - Ensuring the counter can go below zero if decremented enough.
Examples
Example 1:
// In a Vue component:
import { useCounter } from './useCounter'; // Assuming useCounter is in './useCounter.ts'
export default {
setup() {
const { count, increment, decrement, reset } = useCounter(5); // Initial value of 5
return {
count,
increment,
decrement,
reset
};
}
}
Template:
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
<button @click="decrement">Decrement</button>
<button @click="reset">Reset</button>
</div>
</template>
Explanation:
The useCounter composable is initialized with 5. The component displays the count (initially 5). Clicking "Increment" will change count to 6, "Decrement" to 4, and "Reset" will bring it back to 5.
Example 2:
// In a Vue component:
import { useCounter } from './useCounter';
export default {
setup() {
const { count, increment, decrement, reset } = useCounter(); // No initial value provided
return {
count,
increment,
decrement,
reset
};
}
}
Template:
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
<button @click="decrement">Decrement</button>
<button @click="reset">Reset</button>
</div>
</template>
Explanation:
When useCounter is called without an initialValue, it defaults to 0. The component will display 0 initially. Incrementing will make it 1, decrementing will make it -1, and resetting will return it to 0.
Constraints
- The
useCounterfunction must return an object containingcount,increment,decrement, andreset. - The
countproperty must be of typenumber. - The
increment,decrement, andresetproperties must be functions. - The
initialValueargument, if provided, must be anumber.
Notes
- Remember to use Vue's
reffunction to make thecountreactive. - Consider how you will type the return value of your composable for better TypeScript integration.
- This challenge is designed to familiarize you with the basic structure and usage of composables.