The fact that Vue.js 3 already reached the alpha version made me think that... it's time already for some Vue.js 3 tips!

The idea is to give you some tips related to new features you can find on Vue.js 3 as they get available. For now, we'll focus on Composition API, one of the most game-changing features!

This first one is specially focused on showing you a basic step-by-step guide or cheatsheet to migrate object-api Vue.js components to use Composition API. In future tips you'll also see how to apply certain new techniques this API allow us to do as well 😉.

I'll do that by showing you how to convert an Object-API-based component to use Composition API.

For that, let's create a MoneyCounter.vue component that basically shows a money amount and allow us to add/substract quantities to it, implemented using the following code:

< template > < div > < h2 > {{ formattedMoney }} </ h2 > < input v-model = "delta" type = "number" > < button @ click = "add" > Add </ button > </ div > </ template > < script > export default { data : () => ({ money : 10 , delta : 1 }), computed : { formattedMoney() { return this .money.toFixed( 2 ); } }, mounted() { console .log( "Clock Object mounted!" ); }, methods : { add() { this .money += Number ( this .delta); } }, watch : { money(newVal, oldVal) { console .log( "Money changed" , newVal, oldVal); } } }; </ script >

This component has a money state which holds the quantity, the delta that is bound using v-model to the input and later used in the add method to add that quantity to money. The computed property formattedMoney correctly displays the decimal values of money . Finally, I also included a dummy watch and mounted with a console.log statement for the purpose of showing how to migrate it to Composition API.

Take some time to understand this component if you need it.

Right away, create a MoneyCounterComposition.vue component. This component shares the same <template> than the previous, since template is not affected by API's, so copy it from the previous component.

The change is in the <script> part. Let's check first how it'd be all code:

import { ref, computed, watch, onMounted } from "@vue/composition-api" ; export default { setup() { const money = ref( 10 ); const delta = ref( 1 ); const formattedMoney = computed( () => money.value.toFixed( 2 )); onMounted( () => console .log( "Clock Object mounted" )); const add = () => (money.value += Number (delta.value)); const moneyWatch = watch(money, (newVal, oldVal) => console .log( "Money changed" , newVal, oldVal) ); return { delta, money, formattedMoney, add, moneyWatch }; } };

First of all, we're exporting an object with the setup function. This is required and here's where all happens. Now let's focus part by part:

State: it's implemented using ref , and as you can see you can have as many as you want. To access them you don't need to access " this ", since it's just a variable not a "magic" instance thing (yay!), although to change its value you need to access the .value property. You could use reactive as well, but I encourage use to read this article from Jason Yu and use ref as a convention.

Computed: you need to use computed for it. It's basic: it takes a function as its first argument.

Hooks: every hook has its own utility. In the case of mounted hook its onMounted . Same shape as computed : they take a function as their first argument.

Methods: they're just functions, like any other. Nothing special here.

Watch: there are different signatures. That's the one equivalent to watch money , but you can check all shapes in the RFC docs.

Finally, the setup function must return an object containing everything you want to use in the template. Anything that is not there, it won't be accesible from the template.

A little note: you may notice that I'm importing from "@vue/composition-api". That's because I'm using a plugin since Vue 3 is not there yet, but with the plugin we can already use it.

I hope the following image helps you understand how to migrate this component by this side-by-side perspective:

If you want to see with your own eyes that this code truly works, go and check it in this CodeSandbox!

That's it for today's tip!