An ultimate guide to the Vue 3 Composition API

An ultimate guide to the Vue 3 Composition API

The Composition API is an addition to the Vue framework created to address the limitations of the Options API used in Vue 2. The Composition API provides a way to manage reactivity in an application without compromising code organization and readability. As an alternative to the Options API offers more benefits. With the Composition API, you can restructure data, method, computed, and watch, in a clearer structure.

This article will introduce you to the Composition API while comparing it to the options API. At the end of this blog post, you will have a base knowledge of the composition API and its advantages over the options API. To follow along with this article, it is assumed that you have:

  • Knowledge of Vue.js
  • Knowledge of the Options API

Why Composition API?

The Options API is used for creating components in Vue 2. With the Options API, you might face two main limitations when building larger Vue apps/components:

  • Code that logically belongs together might be split across multiple options (data, method, and computed).
  • Reusing logic across multiple components can be tricky or cumbersome.

The Composition API solves the first problem by allowing you to more easily group relevant code together as your code grows. It solves the second problem by enhancing code reusability using composables. It was created for better extensibility and organization of code since Vue projects became harder to manage as they grew in size and complexity. Also, it offers much better TypeScript support.

Let’s take a look at some codes to illustrate the points above.

Options API

Options API uses different code blocks such as data, methods, and mounted to group code logic. As your project grows, readability and maintainability become a problem, and this is one problem that the composition API solves.

export default {
// state
    data() {
      return {
          counter: 0
// methods
    methods: {
        increment(num) {
        this.counter = num++;
    decrement(num) {
      this.counter = num--;
// lifecycle hooks
  mounted() {
    alert('Application started');

Composition API

Composition API allows you to group code logic together inside a setup() function.

<script setup>
import { ref, onMounted } from ‘vue’;

const counter = ref(0);

// methods
function increment(num) {
  counter.value = num++;
function decrement(num) {
  counter.value = num--;

//lifecycle hooks
onMounted(() => {
  alert('Application started');

The Composition API allows you to restructure code segments from options API, i.e., data, methods, and lifecycle hooks, by grouping all of your code that logically belongs together.

Setup function

The setup() function enables you to extract parts of components and group them logically together. It helps you wrap your logic stored in the form of a function. It accepts props and the context object (with which you can emit events and data) as optional arguments. The setup() function returns state and other defined variables so that the component’s template can access them.

Here’s an example of using the setup function:

  setup(props, context) {
    const deleteItem = () => {
      context.emit(“deleteItem”, props)
    return { deleteItem };

An alternative to the setup() function is the <script setup> (recommended by Vue). The <script setup> offers better runtime performance, efficient use of TypeScript, better IDE type-interface support, and a lesser boilerplate to start. For this reason, we’ll use the <script setup> in the rest of the examples in this article.

Open Source Session Replay

OpenReplay is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data.


Start enjoying your debugging experience - start using OpenReplay for free.


The second main feature of the composition API is that it allows you to reuse stateful logic. A composable is a function in which you can wrap your methods, reactive data, watchers, etc., and reuse them in other components. To use composables, you have to import them. Read more about composables.

import { ref } from 'vue'

export function usePerson() {
  const name = ref(‘John’)
  function addSurname(surname) {
      name.value += surname + “ “ + name.value
      return {

Handling Props

Props are a way to pass data from one component to another. The defineProps() method is used to declare props using <script setup>, while in non-script setup components, props are declared using the props property.

Defining Props

<script setup>
const props = defineProps(['name'])

Passing Props

  <Modal title="Greet" :description="isLoggedIn ? 'Welcome!' : 'Please log in'" /> 
<script setup>
  import { ref } from 'vue';
  import Modal from '@/Modal.vue'

  const isLoggedIn = ref(true);

Accessing Props

// Modal.vue component

  <h1>{ title }</h1>
  <p>{ description }</p>
<script setup>
  const props = defineProps({
    title: String,
    description: String

Reactive state

In Composition API, you can add reactive data using ref() and reactive() functions. Reactivity helps sync state changes between your code logic and template elements. When state data is updated in code, the element “reacts” to that change, and its value is also updated.

The ref() and reactive() methods are similar, except that ref() data can accept any type of argument and is accessed using the .value property while reactive() data accepts only objects as argument and is used directly without the .value property.

    import { ref, reactive } from ‘vue’
    const name = ref{'John'};
    const age = reactive(10);

Computed state

Just like you can use computed properties in the Options API, you can also use it in the Composition API inside the setup() function. Computed is a reactive method that generates a new value based on another reactive value. When the reactive value changes, computed fires a callback and generate a new value.

<script setup>
    const data = ref([25,16,17,18,10,33,20]);
    const adults = computed(() => {
        data.filter(item => item >= 18));

Watching values

Reactive values can be watched using watch() and watchEffect() methods. They track changes in reactive values and execute a call-back function whenever those values changes. They are both similar except that the watchEffect() method is executed once initially and then watches for changes afterward.

import { watch, watchEffect } from ‘vue’

const counter = ref(10)
watch { counter, () => console.log(‘counter added’) 

const { counter, () => console.log(‘counter added’)

//Note: the watchEffect() method runs once initially


We’ve come to the end of this article. You’ve learned the basics of Composition API and the benefits it offers over the Options API. Although you can use the Options API in Vue apps, it is ideal to consider using the composition exclusively, especially on more complicated apps and components. However, the Composition API can be too complicated for smaller projects.

This article didn’t cover all the information on working with the Composition API, for example, handling events, using emit() method, etc. That said, I’d advise that you refer to the Vue.js documentation for more information on the Composition API.

If you’re currently using Vue 2, you can migrate your app to Vue 3. If migration becomes a problem for any reason, you can use the new Composition API features in Vue 2 by adding the official Composition API for Vue 2 plugin. Happy coding.

A TIP FROM THE EDITOR: For more on Vue 3, don’t miss our Vue 3 - the Evolution of Vue and Learn The Fundamentals Of Vue With Vue 3 articles.