Hone logo
Hone
Problems

Vue 3 Composition API Counter Component

Create a reusable Vue 3 component using the Composition API and TypeScript that displays a counter and allows users to increment or decrement its value. This challenge will test your understanding of setup function, ref, and basic event handling in Vue 3.

Problem Description

You need to build a CounterComponent that:

  1. Displays a counter value: Initially, the counter should start at 0.
  2. Provides increment and decrement buttons: Two buttons should be present, one to increase the counter value by 1 and another to decrease it by 1.
  3. Uses Vue 3 Composition API: The component's logic must be implemented within the setup function.
  4. Utilizes TypeScript: All logic and types should be defined using TypeScript.
  5. Is reusable: The component should be designed in a way that it can be used multiple times within an application with independent counter states.

Key Requirements:

  • The counter value should be reactive.
  • The component should emit an event whenever the counter value changes.
  • The initial value of the counter should be customizable via a prop.

Expected Behavior:

When the "Increment" button is clicked, the displayed number increases by 1. When the "Decrement" button is clicked, the displayed number decreases by 1. The component should display the current value of the counter. When the initialValue prop is provided, the counter should start with that value. An event named valueChanged should be emitted with the new counter value as its payload whenever the counter is incremented or decremented.

Edge Cases to Consider:

  • What happens if the initialValue prop is not a number? (While not strictly required to handle invalid prop types for this challenge, it's good to be aware).
  • Consider potential for very large or very small numbers (though for this challenge, standard number limits are acceptable).

Examples

Example 1:

Input (Vue Template Usage):

<CounterComponent :initialValue="5" @valueChanged="handleValueChange"/>

Expected Output (Initial Render):

A UI displaying:

  • The number 5.
  • An "Increment" button.
  • A "Decrement" button.

After clicking "Increment" once:

A UI displaying:

  • The number 6.
  • The event valueChanged is emitted with payload 6.

After clicking "Decrement" once (from initial state):

A UI displaying:

  • The number 4.
  • The event valueChanged is emitted with payload 4.

Example 2:

Input (Vue Template Usage):

<CounterComponent @valueChanged="logChange"/>

Expected Output (Initial Render):

A UI displaying:

  • The number 0.
  • An "Increment" button.
  • A "Decrement" button.

After clicking "Increment" three times:

A UI displaying:

  • The number 3.
  • The event valueChanged is emitted three times, with payloads 1, 2, and 3 respectively.

Constraints

  • The initialValue prop should be an optional number. If not provided, it defaults to 0.
  • The component should be a functional component (though a standard SFC is also acceptable for demonstrating setup).
  • The solution should strictly adhere to the Vue 3 Composition API and TypeScript.

Notes

  • Remember to import ref from vue.
  • The setup function returns an object whose properties are exposed to the component's template.
  • You'll need to define props and emit events using the defineProps and defineEmits helper functions available in <script setup>. If not using <script setup>, you'll use props and emit arguments in the setup function.
  • Think about how to make the counter value reactive.
  • Consider how to bind click events to your buttons.
Loading editor...
typescript