Composition API with Vue 3: some differences with Vue 2

vueJS
Tags:

We have already prepared a template for working with Vue 3 using the Composition API, but there is no doubt that getting the most out of Vue 3 requires knowing the differences between Vue 2 and Vue 3. Or rather, what has been added in Vue 3 that makes it worth upgrading.

Moving from Vue 2 to Vue 3

To understand exactly what is involved in migrating to Vue 3, I have taken the From Vue 2 to Vue 3 course that you can find on VueMastery.com. It’s not a very long course, and it gives those of us who already have experience with Vue 2 a good overview of how to modify your habits to migrate.

A classic example to start with: working with lists

Starting from my template (available on GitHub), we are going to prepare a simple example as if we were working with Vue 2, and later, we will do exactly the same using Composition API. With the differences that you will see in the code you can already draw some first conclusions: what we have learned in Vue 2 is perfectly valid.

Obviously, following one path or the other will depend on what you want to achieve and your skill with the Composition API.

We are going to modify the HTML code a little bit, but only to add a second DIV, so that we can load the normal code and the composition API on the same page.

<!DOCTYPE html>
<html lang="es">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
    <title>Vue3 with @manejandodatos</title>
</head>

<body>
    <div id="app">    </div>
    <div id="app2">    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script type="module" src="scripts/index.js"></script>
</body>
</html>

The code in the module index.js

Index.js is a Javascript module where everything in our app starts. The code does not vary much from the template, but now, we include as a novelty the import of 2 objects from our app.js component.

    import {tReactive, vue2} from '../components/app.js';

    const { createApp } = Vue;
    
    createApp(tReactive).mount('#app');
    createApp(vue2).mount('#app2');

As you can see, this file is not complex. The only thing we do is to mount each one of the objects tReactive and Vue2 in a different div. As you can imagine, the behavior of both DIVs will be the same, because the intention is to see the differences between Vue 2 and Vue 3, with Composition API.

Addnew.js, a new module to add new data

Before we continue, we are going to create the addnew.js file, also in the same components directory, and it is simply a small component where we work with the form to insert new data to the list.

The code is quite simple, and the known Vue 2 style has been used (we will have time to improve it).

export default {
        name: 'addNew',
        data() {
            return {
                tarea:""
            }
        },
        methods: {
            enviar() {
                this.$emit('nuevo', this.tarea);
                this.tarea = "";
            }
        },
        template: `
        <form @submit.prevent="enviar">
            <input v-model.lazy="tarea" />
            <button type="submit">Add</button>
        </form>
        `
};

The code is perfectly assimilable to Vue2 components. Among the details included is the inclusion of name, to give a name to the component. The reactive data are those included in data and the send method has been prepared, whose purpose is to “emit” an event with the new data.

As a peculiarity, and to avoid “reloading” everything, it is important the detail of .prevent in the @submit of the form. And also, .lazy has been used in the input so that everything is updated when the focus is lost.

The code of app.js using Composition API

Surely, some things can be reduced or done in another way, but I have thought convenient to use some variables to avoid rewriting code that can be reusable. I’ll start with the code, and then I’ll tell you the details:

import addNew from "./addnew.js";
const { reactive } = Vue;

const lists_def = ["uno", "dos"];
const template = `
<div>
  <h1>{{title}}</h1>
  <ul v-for="(i, index) in lists" key="index">
    <li>{{ i }}</li>
  </ul>
  <addNew @nuevo="nuevo"></addNew>
</div>
`;

const tReactive =  {
    name: 'tReactive',
    components: { addNew }, 
    setup() {
        const title = "List with Vue 3 Composition API";
        let lists = reactive([...lists_def]);        
        const nuevo = val => {
          lists.push(val);
          console.log(lists);
        }
        return { title, lists, nuevo };
    },
    template: template,
};

const vue2 = {
  components: { addNew  },
  data() {
    return {
      title: "List with Vue3",
      lists: [...lists_def],
    }
  },
  methods: {
    nuevo(val) { this.lists.push(val)  }
  },
  template: template,
}
export { tReactive, vue2} ;

The imports of “components” must be done at the beginning, and this is where we import the AddNew.js form, which is a component. We include it in the variables inside components: { addNew }. The reason is simple: to tell Vue that we want to use that component inside another component.

Next we import reactive from Vue, that we already saw in a previous entry, to make reactive the variables using Composition API. This is important, because in case of not using it, the variable will be updated, but it will NOT be reflected in the DOM. And normally, when you make a modification, “something” will see this modification in the DOM.

Next we define two variables to avoid repeating code: one is list_def which is a list of values, and template, which is the one that contains our template and so we can use it with the vue2 and Composition API variable.

Next, we define tReactive, which is what we will prepare with Composition API. Besides the name, template and components, the important code is in setup and in what it returns.

In setup you define everything that theoretically goes in data (in vue2) and also include everything required by the template, such as the function nuevo.

We continue with the variable vue2, which is the definition of a component in the most traditional way: we define data, and in methods the code includes the nuevo function.

The last line is the one that exports the two variables: tReactive and vue2, which basically does the same thing, but in a different way.

Vue using Composition API and with the Vue 2 style

In the image above we have added a different element to each one.

First conclusions on the differences between Vue2 and the Composition API

Two paths, arriving at the same point. Neither is better than the other, only that the rules of one and the other are different. I, for the moment, am just getting to know the Composition API, because I already know the other way from Vue 2. Undoubtedly, the fact that you can work with both will allow you to use the best form depending on the objective to be achieved, and obviously, on your expertise as a developer.

We will continue working in the next blog posts to improve the knowledge of Composition API with more news. The full code is available at Github.

And finally, this example has many improvements, but the main thing is that you learn a little bit the differences between the classic programming of Vue 2, compatible with Vue 3, and using Composition API.

Personally, I found this video about Vue 3 very useful. 10 hours of cool Vue 3 material.

https://www.youtube.com/watch?v=e-E0UB-YDRku0026t=7110su0026ab_channel=Bitfumes

I took more than 10 hours to decipher all the secrets of Vue 3.

Vuetify and Vue 3

I would have really liked to create a next post with everything done in this same post, but using Vuetify. However, at the moment (March – Aplir 2021), Vuetify 2 is not supported in Vue3. So, we are in no hurry to keep learning little by little while Vuetify 3 arrives, or the first betas begin.

The only viable solution to use Composition API with Vuetify is to continue using Vue version 2, adding the Composition API plugin, with its limitations.

Happy coding!