Brief Look on Vue 3.0 Composition API: More Readable Components

Arik Sasmita
DANA Product & Tech
6 min readMay 11, 2020

With the current Vue 2.x way of building components, we’re separating it by the option, not feature. What this means is that for example, a single toggling state for showTitlewill need to have reactive data in data()and a methodto toggle the state. For a small simple component, this won’t be a problem. But as the component grows, more functionality will be added, thus making reading the whole feature more difficult. An example can be seen below.

Now that might still be readable to some extent, but as you can see we started to get different concerns of functionality split by dataand methods. This will continue to get more complex when the component grows, let alone if we need to add computedor lifecycle hooks.

Now on Vue 2.x, we have mixinsthat can address this concern. Mixins can be used for functionality purposes, making related data end methods in one file, then importing that file wherever it needed. For me, this still looks relevant and is the way to go for most cases (this post doesn’t imply we should make it obsolete either). The downside on this, however, is that sometimes we need to know what happens in it, to decide if we can use it as-is, or we need to adjust it for our needs. We’ll need to open the file, read again and when finished, check other places that use it making sure none of them broke. Other things are that there is a great potential that mixins can have similar names, which will make various issues.

Composition API

The upcoming Composition API is the solution Vue 3 introduces to resolve the above issues. At the moment of writing (May 2020) it is still in beta, but we can already try it. It can make related data, methods, and functions scoped in one place instead of spread all over the file. We can use it in existing Vue 2.x projects by installing an additional npm package.

npm i --save @vue-composition-api

Afterward, we will need to import the package in our app.jsfile as we can see below.

import Vue from "vue";
import VueCompositonApi from "@vue/composition-api";
...
Vue.use(VueCompositonApi);

If you are starting from scratch with Vue 3.0 however, we can directly import everything in a .vue file from vue. For example:

import { refs, reactive } from "vue";

We can now access the setup() function inside our .vue file. This function will run on component initialization, acts as a replacement to beforeCreate and created lifecycle hooks. Now let’s see how we can use some of this enhancement compared to existing Options API in the previous Vue version.

Data Reactivity

Reactivity is the main advantage when using Front End Javascript framework like Vue. In Vue 2.5 we are defining our data in data () function or data object. In Composition API, we need to import ref or reactive from vue/composition-api to achieve the same functionality.

Both refand reactive can make a value reactive, but they have slight differences in use and access. ref can directly be assigned to a single variable or constants, while reactive can be used as the usual data function we use often in Vue 2.0, it will make the whole Object it covers to be reactive. If you can see above, ref will need .value for us to have access to its content, while reactive can be accessed directly.

Another way we can implement reactivity is by wrapping all values as an object in a reactive function. This way, if we need to have a computed value, we can directly access it without specifying .value. For example, we will use the above code and wrap the values in reactive function, then add a computed value that accesses the result value.

There is a drawback from this setup though. We will need to change how we access it in the template as well.

Naturally, if you are familiar with ES6, we will first think that we can just spread the object upon exporting like return { …allData, logData }. But this will throw an error. Even if you specify it one by one like allData.total, the value will lose its reactivity.

For this, Vue 3.0 introduces toRefs that will do just this. The function will convert each of the object values and map it in their own ref. With this applied, we can access the values in the template like before.

If we don’t need to access any other than the reactive value, we can simply do return …toRefs(allData)

Computed and Watch

Computed values can be added by using computed function imported from Vue, similar to reactive. It receives a function that returns the computed value as we have previously in Options API.

As for the Watch, we can assign a watch function using watch, also imported from vue. What we can do in there is similar to what we have in the previous version.

Props

The props is similar to previous version. But in order to have it accessible in setup function, we need to pass it in as an argument. The no-destructure rule still applies here, as if we do it, we will lose the reactivity.

File Management

Knowing above that much, some of us might think that this can make the setup function gigantic in no time. That goes in contrast with the readability improvement theme we have here. But fear not! As handy as we have mixins previously, we can also outsource related functions into separate files. They are functions after all.

Emit

One change for emit in the new version is we are now encouraged to declare it in a separate emits property. This acts as a self-documentation of the code, ensuring that developers that come to a component they didn’t make understand the relations to its parent.

Similar to props, we can also validate the payload passed and returns a Boolean as a result.

Lifecycle Hooks

We can also set lifecycle hooks in setup function by importing onXXX beforehand. An important note on this one is we can’t access this in the setup function. If we still needed, for example, emit to parent on mounted, using themounted hook from Options API seems to be the way for now.

Multi Root Template

As you may already know with Vue 2.x, we can only have one root element in the template. Not anymore in Vue 3.0 though. Thanks to the Fragments feature, having only one root element is no longer mandatory.

Note: Your linter might complain about this being illegal. Mine does. Best to save this till we have a proper public release. But still exciting nonetheless.

Conclusions

Ease of code writing and readability seems to be one of the main focuses on the upcoming update of Vue. Apart from under the hood optimizations and better support of TypeScript, these are all exciting updates to look forward to. Especially they can be treated as add-on updates on an existing app rather, than complete rewrite, as the current API still supported.

There’s so much more to the features listed as upcoming updates on the next version on Vue. you can see the complete list and updates over in Vue’s RFCs repo here: https://github.com/vuejs/rfcs.

Other features worth their in-depth article with detailed samples. More on that will be coming.

Sources

--

--