Migrating components from Option API to Composition API on Vue 🛠️

Nico Montiel - Feb 19 '23 - - Dev Community

Today I will show you how to migrate your components from the "old" Option API to the new Composition API on Vue 3.

First of all, what is the composition api?

Good question! The official documentation says

Composition API is a set of APIs that allows us to author Vue components using imported functions instead of declaring options.
Composition API is a built-in feature of Vue 3 and Vue 2.7. For older Vue 2 versions, use the officially maintained @vue/composition-api plugin. In Vue 3, it is also primarily used together with the <script setup> syntax in Single-File Components.

Okay, great, but why should I use the Composition API?

The primary benefit of the Composition API is that it enables clean, efficient logic reuse in the form of composable functions. It solves all the drawbacks of mixins, the primary logic reuse mechanism for the Options API.
Also, it has more adeventajes like:

  • More Flexible Code Organization.
  • Better Type Inference.
  • Smaller Production Bundle and Less Overhead.
  • Better use with Typescript.

Okay, so how are we going to do this?

I prepared this Vuejs component and we will migrate it piece by piece.

1. Components.
With the Composition API, you don't need to declare the components you want to use, just import them and they will be available in your template.

2. Props.
You can define the props in much the same way as before. You need to declare a variable (usually called props) and use the defineProps method. This method is automatically available inside the script setup tag.

const props = defineProps({
    userId: {
        type: String,
        required: true,
    },
    cartId: {
        type: String,
        required: true       
    },
})
Enter fullscreen mode Exit fullscreen mode

3. Event emitters.
As with props, you need to define a constant and use a method available within the script setup tag. This is called defineEmits.

const emit = defineEmits(['checkout'])
Enter fullscreen mode Exit fullscreen mode

4. Data
With the data, we can now see much cleaner and more readable javascript. For the data on your component, you have two cases: data with reactivity, or a simple constant.

For the data with reactivity, you need to import ref and put the initial value of the variable inside the method.

import { ref } from 'vue'

const items = ref([]) // This is the initial value, we are going to fill it later.
Enter fullscreen mode Exit fullscreen mode

And for the constant variable, as easy as javascript.

const maybeAConstantObject = {
    someKey: 'someValue',
    anotherKey: 'anotherValue'
}
Enter fullscreen mode Exit fullscreen mode

5. Methods.
Methods, like variables, are now just simple javascript functions, lets show some examples:

 function addItem(item) {
    items.value.push(item);
}

function proceedToCheckout() {
    // Here you can also see how emit an event.
    emit('checkout', items.value);
}
Enter fullscreen mode Exit fullscreen mode

6. Computed properties
Okay, this is a bit more tricky, but still not complicated. To do this, we need to import the computed method and inside it, we put a callback that returns the value of the property.

import { computed } from 'vue'

// So now this variable will return the sum of all the items in the cart, and it will be executed everytime the `items` change.
const total = computed(() => {
    return items.value.reduce((total, item) => {
        return total + (item.price * item.quantity)
    }, 0)
})
Enter fullscreen mode Exit fullscreen mode

7. Watchers
As in some previous cases, you need to import the watch method from Vue, and this takes two arguments; the first is the data you are watching (this should be reactive data, like items in this case), and the second argument is a callback that is invoked when the data changes.

import { watch } from 'vue'

// The console.log will be executed every time items changes.
watch(items, () => {
    console.log('Cart items changed')
})
Enter fullscreen mode Exit fullscreen mode

8. Created
So we don't have a specific onCreated here, we just need to create the function and initialise it inside the script setup. Also, I leave here the list of Lifecycles of a Vue component as a reference. Remember, here the DOM doesn't exist yet.

<script setup>
    // This will be executed when the component is created.
    console.log('Cart created')
</script>
Enter fullscreen mode Exit fullscreen mode

9. On Mount
This is a lifecycle that exists in the API, so we need to import it from vue. Inside it takes a callback that is executed after the component is mounted. Here you already have access to the DOM.

// This call to the endpoint will run when the component is mounted.
onMounted(() => {
    fetch('/api/cart/' + props.cartId)
        .then(response => response.json())
        .then(items => items.value = items)
        .catch(error => console.error(error));
})
Enter fullscreen mode Exit fullscreen mode

This is the final result:

To summarize

Migrating from the Option API to the Composition API is not something complicated, from my own experience, after a few components, it will be an easy task for you.
Now the question, should you do it? It's up to you, it's not necessary and if you prefer the Option API, you won't have any problem with it in the near future.

If you have any recommendation or some case is missing, let me know and I can add it :)

That's all, I hope it can be helpful for you 🥳

. . . . . . . .