Understanding Vue 3 Composition API: A Step-by-Step Tutorial
Tags: vue, frontend, tutorial, javascript
Published: 2024-05-27 05:17:47


Hey there, fellow coder! 🌟 If you're diving into Vue 3, you've probably heard about the Composition API. It’s one of the coolest new features that makes organizing and reusing code a breeze. Whether you're new to Vue or coming from the Options API, this step-by-step tutorial will guide you through the Composition API with clear explanations and practical examples. Let's get started!

## What is the Composition API?

The Composition API is a set of additive APIs that allow you to use function-based composition to build your components. It’s designed to improve code organization and reuse, especially in larger applications.

### Why Use the Composition API?

- **Better Code Organization**: With the Composition API, you can group related logic together in a more natural way. This makes your components easier to read and maintain.
- **Reusability**: The Composition API allows you to easily reuse logic across different components, making your code more modular and less repetitive.
- **TypeScript Support**: The Composition API has improved support for TypeScript, making it easier to write type-safe code.

## Setting Up Your Project

First things first, make sure you have Vue 3 set up. If you don’t, you can quickly create a new project using the Vue CLI:

```bash
npm install -g @vue/cli
vue create my-vue-app
cd my-vue-app
npm run serve
```

Now, let’s dive into some examples!

## Basic Example

### The Options API Way

Before we jump into the Composition API, let’s see how we’d typically do things with the Options API:

```javascript
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="updateMessage">Update Message</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, Vue!'
    }
  },
  methods: {
    updateMessage() {
      this.message = 'Hello, Composition API!'
    }
  }
}
</script>
```

### The Composition API Way

Now, let's refactor this using the Composition API:

```javascript
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="updateMessage">Update Message</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const message = ref('Hello, Vue!');

    const updateMessage = () => {
      message.value = 'Hello, Composition API!';
    };

    return {
      message,
      updateMessage
    };
  }
}
</script>
```


- **ref**: The `ref` function is used to create a reactive reference to a value. This means that when the value changes, Vue will automatically update the DOM to reflect the new value. To access the value stored in a `ref`, you need to use the `.value` property.
- **setup()**: The `setup` function is a new lifecycle hook in Vue 3 where you can define your component's logic using the Composition API. This function runs before the component is created, allowing you to set up reactive state and other functionalities early on.

## Reactive State

### Using `reactive`

If you need a more complex state, use `reactive` to create a reactive object:

```javascript
<template>
  <div>
    <p>{{ state.count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script>
import { reactive } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    const increment = () => {
      state.count++;
    };

    return {
      state,
      increment
    };
  }
}
</script>
```


- **reactive**: The `reactive` function converts an object into a reactive object. This means that Vue will track changes to any properties within the object and update the DOM accordingly. Use `reactive` when you have a state that involves multiple properties or more complex data structures.

## Watchers and Computed Properties

### Watchers

Watchers allow you to perform side effects in response to state changes. This is useful for tasks like making API calls when a certain piece of state changes.

```javascript
import { ref, watch } from 'vue';

export default {
  setup() {
    const count = ref(0);

    watch(count, (newCount, oldCount) => {
      console.log(`Count changed from ${oldCount} to ${newCount}`);
    });

    const increment = () => {
      count.value++;
    };

    return {
      count,
      increment
    };
  }
}
```


- **watch**: The `watch` function is used to track changes to a reactive value or a ref. When the value changes, the callback function is executed. This is useful for scenarios where you need to perform actions based on state changes, like making API calls or updating other parts of your application.

### Computed Properties

Computed properties are reactive and cache their results, which means they only recompute when their dependencies change. This is useful for expensive calculations that depend on reactive state.

```javascript
import { ref, computed } from 'vue';

export default {
  setup() {
    const count = ref(0);

    const doubleCount = computed(() => count.value * 2);

    const increment = () => {
      count.value++;
    };

    return {
      count,
      doubleCount,
      increment
    };
  }
}
```


- **computed**: The `computed` function creates a reactive value that is automatically updated when its dependencies change. It also caches the result until the dependencies change, which can improve performance for expensive calculations. Computed properties are useful for deriving state that depends on other reactive values.

## Lifecycle Hooks

### Using Lifecycle Hooks

You can use lifecycle hooks within the `setup` function using Vue's lifecycle methods. This allows you to perform actions at specific stages of the component's lifecycle, such as when the component is mounted or unmounted.

```javascript
import { ref, onMounted, onUnmounted } from 'vue';

export default {
  setup() {
    const count = ref(0);

    onMounted(() => {
      console.log('Component mounted');
    });

    onUnmounted(() => {
      console.log('Component unmounted');
    });

    const increment = () => {
      count.value++;
    };

    return {
      count,
      increment
    };
  }
}
```


- **onMounted**: The `onMounted` function is called when the component is mounted to the DOM. This is a good place to perform setup tasks that require access to the DOM, such as fetching data or initializing third-party libraries.
- **onUnmounted**: The `onUnmounted` function is called when the component is unmounted from the DOM. This is a good place to perform cleanup tasks, such as removing event listeners or cancelling API requests.

## Composable Functions

### Creating Reusable Logic

One of the main benefits of the Composition API is the ability to extract and reuse logic across components. These reusable pieces of logic are called composables.

```javascript
// useCounter.js
import { ref } from 'vue';

export function useCounter() {
  const count = ref(0);

  const increment = () => {
    count.value++;
  };

  return {
    count,
    increment
  };
}
```

### Using Composables in Components

```javascript
<template>
  <div>
    <p>{{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script>
import { useCounter } from './useCounter';

export default {
  setup() {
    const { count, increment } = useCounter();

    return {
      count,
      increment
    };
  }
}
</script>
```


- **Composables**: Composables are functions that encapsulate and reuse logic across components. They allow you to organize your code more effectively and make it easier to share functionality between different parts of your application. By using composables, you can keep your components clean and focused on their specific responsibilities.


The Vue 3 Composition API is a powerful tool that enhances the flexibility and organization of your code. By understanding and using `ref`, `reactive`, `computed`, `watch`, and lifecycle hooks, you can create cleaner and more maintainable components. Don’t be afraid to experiment and refactor your existing components to take advantage of these new capabilities. Happy coding! 🚀

If you have any questions or need further clarification, feel free to reach out. Let’s connect and grow together on this exciting journey of web development! #connect #100DaysOfCode

Twitter:  [@delia_code](https://x.com/delia_code)

Instagram:[@delia.codes](https://www.instagram.com/delia.codes/)

Blog: [https://delia.hashnode.dev/](https://delia.hashnode.dev/)