fbpx

A First Look at Vue3 — A Vue Composition API Tutorial

person typing at computer

With the release of Vue 3.0 near, there are still parts that you can implement in Vue2 projects. One of the most popular features that many developers have been exploring is the Vue Composition API.

It’s actually pretty easy to start using in existing projects — so let’s not waste time and just get into it.

So what is the Vue Composition API?

The Composition API allow developers to define reactive component logic more intuitively by allowing grouping of code for a specific feature (search, for example).

In comparison to the current API, the new Component API is also more scalable and reusable between several components.

Essentially, it allows us to group component logic all together into neat reusable Composition Functions.

If you want to know more about the technical details of the Composition API, I would definitely go ahead and check out the documentation that explains it more in-depth.

Vue Composition API Example

For this example, we’ll create a Grocery List component that displays a list and allows a user to add/remove items.

First, let’s see what this would look like using the current Vue 2 API.

<template>
  <div>
    <input type="text" v-model="input" placeholder="Add Grocery" />
    <input type="submit" @click="addGrocery()" />
    <ul>
      <li v-for="(item, index) in groceries" :key="item">
        {{ item }}
        <button @click="deleteGrocery(index)">X</button>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      input: "",
      groceries: []
    }
  },
  methods: {
    addGrocery() {
      this.groceries.push(this.input);
      this.input = "";
    },
    deleteGrocery(index) {
      this.groceries.splice(index, 1);
    }
  }
};
</script>

This is the functionality to maintain items of a grocery list. Now imagine all of the other features we may want for this component: searching, sorting, price matching, etc. It would get cluttered quickly. And if we needed more advanced functionality like custom Vue watchers or API calls, it would become a mess.

This should just show a simple app like this.

All of these features would add a lot of code to the data and methods sections of the component. Making it harder to trace individual features. This is where the Composition API comes in to play.

Implementing the Vue Composition API

Now, let’s convert this to include the new Composition API. First, we’ll have to install it using npm install --save @vue/composition-api

Then, to actually import it onto your project — we’ll have to include it in the main.js file. To do this, just add the following lines:

import VueCompositionApi from '@vue/composition-api' 
Vue.use(VueCompositionApi)

I’ll show the new component and then break it down even further.

This should have the exact same functionality as the first component we created.

<template>
  <div>
    <input type="text" v-model="state.input" placeholder="Add Grocery" />
    <input type="submit" @click="addGrocery()" />
    <ul>
      <li v-for="(item, index) in state.groceries" :key="item">
        {{ item }}
        <button @click="deleteGrocery(index)">X</button>
      </li>
    </ul>
  </div>
</template>

<script>
import { reactive } from "@vue/composition-api";
export default {
  // called after beforeCreate and before create hooks
  setup() {
    const { state, addGrocery, deleteGrocery } = useGroceryList();
    return { state, addGrocery, deleteGrocery };
  }
};
/* Can be imported from an external file as well */
function useGroceryList() {
  // vue composition api exposes the vue core reactive capabilities
  let state = reactive({
    input: "",
    groceries: []
  });
  function addGrocery() {
    state.groceries.push(state.input);
    state.input = "";
  }
  function deleteGrocery(index) {
    state.groceries.splice(index, 1);
  }
  
  return { state, addGrocery, deleteGrocery };
}
</script>

Wait what’s going on here?

You may notice how the organization of the script looks entirely different. Let’s dive into it a little bit.

First, the data and methods options are completely gone, and instead, there is this new setup method. This method is called after the lifecycle hook beforeCreate and prior to create .

While you can declare the state variable and methods inside this setup method, the way this example works has all of the grocery list functionality contained in its own method. This can also be imported from a reusable external file. All this method has to do is return the variables and functions it wants visible from other methods.

setup() {
    const { state, addGrocery, deleteGrocery } = useGroceryList();    
    return { state, addGrocery, deleteGrocery };
}

Then, there is this state variable thing. An important thing to notice is that it points to reactive values — this is one of the changes coming in Vue3 — the ability for developers to directly control what reactive elements they expose. While this does mean we have to reference the variables as state.input in the template, it gives us more precision and lets us see exactly what is being exported from each method.

let state = reactive({
    input: "",
    groceries: []
});

Instead of having to declare all of our functions in one broad methods option of a component, we can just declare them within our useGroceryList method and group them together. This is extremely helpful down the line when there are dozens of different features and methods in a single component.

function addGrocery() {
    state.groceries.push(state.input);
    state.input = "";
}
function deleteGrocery(index) {
    state.groceries.splice(index, 1);
}
return { state, addGrocery, deleteGrocery };

It’s important that everything we want to be able to access from the template is returned by both the useGroceryList() and setup() methods.

How is this better?

There are three huge pros for using the Composition API as opposed to Vue 2’s current API for implementing component logic: readability, scalability, and familiarity.

1. Readability

In Vue 2, each component has so many different parts that are required to successfully have reactive logic: data, computed, methods, etc.

In larger-scale applications with hundreds/thousands lines of code, these sections can be very far from each other which makes it harder to trace code and debug declarations, logic, etc.

Composition Functions encompass all of the declarations and logic — allowing for more readable and easier to follow code.

2. Scalability

In addition to Composition Functions allowing for code to be more modular and organized, it also allows code to be maintained and scaled much easier.

Right now, there are a few ways to reuse component logic, with the most popular method being VueJS Mixins. However, mixins come with a few limitations.

First, mixins can get tricky when it conflicts with variables names/methods inside the component. Second, and more importantly, mixins are not flexible — they are defined and then imported into a component, as is.

With Component Functions, all of the data required for a specific feature is self-contained and will not conflict with the component. Also, since they are just a typical function, they can take different parameters and adapt to each component’s needs.

3. Familiarity

As you likely saw in the example, the syntax of these functions is very intuitive for people familiar with Javascript. Right now, you would need to know a lot more about VueJS specific lifecycle hooks and component architecture to implement a feature. But by exposing Vue’s reactive capabilities, with the Composition API, Vue 3 has made it much simpler.

And in a language that is already extremely beginner-friendly, this only makes it even better.

In Conclusion…

The Composition API is a great way to make your code more readable and maintainable. It will help larger Vue projects be more modular and reusable. Saving developers a TON of headaches.

This is only the tip of the iceberg of changes coming in Vue 3. However, it’s is a very promising sign of the developer-friendly changes that the Vue Team is making. It seems like they’ve discovered many pain points and have trying to provide good solutions without a steep learning curve

Share Your Thoughts