Options API vs. Composition API

Haidi Zakelšek
CodeX
Published in
5 min readOct 18, 2022

--

If you’re starting a new project in Vue 3 or if you’re still deciding whether or not to migrate an existing project to the latest Vue.js version, this article is for you.

Let’s get started

Up until Vue 2, there was one way to create components in Vue, with the methodology now known as the Options API. With Vue 3, a new methodology was introduced called the Composition API and you might be wondering what the difference is? In this article we’ll take a look at how those two differ.

Let’s start with looking at a simple setup withOptions API:

export default {
data() {
return {
name: 'Vue 3 App',
};
},
methods: {
showTxt() {
console.log(`this is ${this.name}`);
},
},
mounted() {
this.showTxt();
},
};

If we take a look at the code, we notice 3 things, that are the building blocks of the Options API:

  • data: a function that returns the initial reactive state for the component instance,
  • methods: declares methods to be mixed into the component instance. Declared methods can be directly accessed on the component instance, or used in template expressions. Avoid using arrow functions when declaring methods, as they will not have access to the component instance via this,
  • mounted: this is a lifecycle hook, the component is mounted when it’s been created and inserted into the DOM.

Other common things we can run into with Options API and are not in the code above are:

  • props: components require explicit props declaration so that Vue knows what external props passed to the component should be treated as fallthrough attributes,
  • watch: declares watch callbacks to be invoked on data change. The watch option expects an object where keys are the reactive component instance properties to watch (e.g. properties declared via data or computed) — and values are the corresponding callbacks.

Now let’s take a look at the same example, but using Composition API:

export default {
setup() {
const name = ref('Vue 3 App');

const showTxt = () => console.log(`This is ${name.value}`);

onMounted(() => {
showTxt();
});

return { name };
},
};

As we can see from the code, Composition API only uses setup hook to define the component, which means a lot less code. Another important part of the code is ref, which is what makes the data reactive. It returns an object with a value property.

Code Sharing

One of the biggest differences between Options API and Composition API is the way they implement code sharing. Options API has two ways of sharing code, mixins and renderless components. Mixins can be a bit tricky to use, because they make it hard to determine where parts of code come from.

According to the docs, mixins are a flexible way to distribute reusable functionalities for Vue components. A mixin object can contain any component options. When a component uses a mixin, all options in the mixin will be “mixed” into the component’s own options. Here is an example of a mixin:

// define a mixin object
var myMixin = {
created: function () {
this.helloWorld()
},
methods: {
helloWorld: function () {
console.log('hello from my mixin!')
}
}
}

// define a component that uses this mixin
var Component = Vue.extend({
mixins: [myMixin]
})

However, using mixins can be difficult to debug and understand for new developers, especially when they’re dealing with global mixins. Their use can also lead to naming conflicts with components.

With Composition API, there is no need for mixins. Inside the setup hook, we can group parts of code by logical concern. Then, we can extract pieces of reactive logic and share them with other components.

Now let’s take a look at renderless components. A renderless component is a component that doesn’t render any of its own HTML. Instead, it only manages state and behaviour, which gives the parent component complete control over what should be rendered. That means, that if you move logic out of a UI component and into a renderless component, you can reuse it.

Composables

Composition API also supports renderless components, in fact, it’s one of the things Composition API and Options API have in common. However, a major advantage of Composition API are composables. They are reusable pieces of code and thanks to them, we can write reactive code anywhere. We’re not bound to the scope of a Vue component anymore. Here is a simple example of counter composable:

import { computed, ref } from 'vue';

export function count() {
const counter = ref(0);
const addOne = () => { counter.value += 1 };

return {
counter,
addOne,
};
}

And here we can see, how to use it in a component.

<template>
<div>Count: {{ counter }}</div>
<button @click="addOne">
+
</button>
</template>

<script>
import { count } from '../composables/counter-example';

export default {
setup() {
const {
counter,
addOne,
} = count();

return {
counter,
addOne,
};
},
};
</script>

Composables act as an external function that extracts reactive state and functionality to be used across several other components. They can alternatively be called composition functions. With composables, we can tell exactly where our reusable data and functions come from.

Another major advantage of Composition API is that it makes constants and dependencies available in the template:

<template>
<div>
<button @click="create">
Save
</button>
</div>
</template>

<script>
import { create } from './services';

export default {
setup() {
return {
create,
};
},
};
</script>

When doing the same thing using the Options API, it can feel awkward. You either have to add constants and dependencies to your data option or use the created hook to add non-reactive variables to the this context. Composition API saves us some trouble here, as we can simply export them from setup hook and make them available inside the template.

This about sums up the comparison and to conclude things, if you came to a point, where you decided to migrate to the latest version of Vue, as of reasons stated above, Composition API may be worth the trouble as it optimizes the code very nicely and will consequently give your app a better performance. If you are starting from scratch, Composition API would be recommended.

--

--