From Vue2 Master to Vue3 Noob

so I used to tell myself I was good at building webapps with vue, but then the vue3 nation attacked (yes, an avatar reference). with this introduction to vue3, a lot of things changed, I like to think about it as the react hooks change but for vue, the main thing I consider that is a major and it’s worth getting used to it and learn is theComposition APIwhich I’ll be talking more in detail while creating a simple webapp to display some pokemon data

Setup()

Vue3 introduces a new component option called setup, which is the entrypoint for the composition API, it’s important to know that the code written here is executed before the creation of the component therefore thedata, computed, and method options aren’t available inside of it.The setup component options contains two parameters

  • props
  • context (which contains attrs, slots, emit)

In this example I’ll be getting the pokemonId prop or if it doesn’t exist I’ll be assigning one randomly, then I’ll call the API to get the pokemon sprite, the return of the setup options allows you to use those values on the template

setup(props) {
    const pokemonId = props.pokemonId || Math.ceil(Math.random() * 500)
    const pokemonSprite = getPokemonData(pokemonId); //magic function that returns a sprite
    return {
        pokemonId,
        pokemonSprite
    }
}

after this we can just do this inside the template to show the sprite image:

<template>
    <img :src="pokemonSprite" alt="pokemon sprite" />
</template>

Ref() and Reactive()

Vue3 by default doesn’t make every variable reactive, you have to define it yourself using the newref(),reactive()methods

these methods are really similar, the main difference is that is recommended to use ref() on data types (ints, bools, strings, etc…) and to use reactive() on data structures (arrays, sets, json, etc…)

for example, if we want to add a button to randomize a pokemon sprite on click, we need to make the pokemonId prop reactive:

import { ref } from 'vue'
setup(props) {
    let pokemon = ref({})
    const getPokemonData = async (pokemonId) => {
        const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonId}`)
        pokemon.value = await response.json();
    }
    getPokemonData(props.pokemonId);
    return {
        pokemon,
        getPokemonData
    }
},
methods: {
    randomize() {
        this.getPokemonData(Math.ceil(Math.random() * 500));
    }
}

and then in our template we can just do this:

<template>
    <div v-if="pokemon.sprites">
        <img :src="pokemon.sprites.front_default" alt="pokemon sprite" />
        <button @click="randomize">Randomize</button>
    </div>
</template>

Lifecycle hooks

Another new addition to vue3, is the ability to call lifecycle hooksonly inside the setup component option, replacing all the other components options we used to have(mounted {}, created{}, etc…) with the new variants (onMounted(), onCreated(), etc…) this makes the code more readable since in the setup, you’ll be declaring all the initialization of your component in a single place

we can change our pokemon randomizer code to make use of the onMounted hook inside the setup

import { ref, onMounted } from 'vue'
setup(props) {
    let pokemon = ref({})
    const getPokemonData = async (pokemonId) => {
        const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonId}`)
        pokemon.value = await response.json();
    }
    onMounted(getPokemonData(props.pokemonId));
    return {
        pokemon,
        getPokemonData
    }
},

Script setup

Now that I understand how the setup worked, I wanted to go even further explorating the<script setup>proposal after playing with it for a couple of minutes, I understood how awesome it is! the time saving and less code written are really good benefits of it, it adds a couple of new different syntax for props, but nothing to extreme, this is how the pokemon randomizer code looks like with the script setup:

<script setup>
import { ref, onMounted } from 'vue'
const props = defineProps({
  pokemonId: Number,
});
let pokemon = ref({})
const getPokemonData = async (pokemonId) => {
    const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonId}`)
    pokemon.value = await response.json();
}
const randomize = () =>  {
    getPokemonData(Math.ceil(Math.random() * 500));
}
onMounted(getPokemonData(props.pokemonId));

you can check the source code inhere

Sources

cd …