Vue 3 Composition API vs. Options API

  You block advertising 😢
Would you like to buy me a ☕️ instead?

When migrating from Vue 2 to Vue 3 or starting a new Vue 3 project, many people wonder if they should continue using the Options API or go all-in on the Composition API. I advise using the Composition API (for new components) exclusively ASAP and never looking back.

// Options API
export default {
  data() {
    return {
      name: 'John',
  methods: {
    doIt() {
      console.log(`Hello ${}`);
  mounted() {
// Composition API
export default {
  setup() {
    const name = ref('John');
    const doIt = () => console.log(`Hello ${name.value}`);
    onMounted(() => {
    return { name };

The Options API uses options like data, methods, and mounted. With the Composition API, we have a single setup hook in which we write our reactive code.

What Makes the Composition API Better than the Options API?

Short answer: code sharing. Inside the setup hook, we can group parts of our code by logical concern. We then can extract pieces of reactive logic and share the code with other components.

On the other hand, with the Options API, we had two main approaches for sharing code between components: Mixins and Renderless Components. Thanks to the Composition API we never have to use Mixins again. Mixins make it hard to determine where certain parts of logic are coming from inside a component that uses them. But I think Renderless Components are still a valuable tool even with the possibility of using Composables for sharing code between components.

Code Sharing with Composables

Thanks to the Composition API, we can write reactive code anywhere. We’re not bound to the scope of a Vue component anymore. We call those pieces of reusable reactive code Composables.

// src/composables/user-comments.js
// ...

export function useUserComments({ user }) {
  let { data: comments, error } = useSwrv(() => ({ uid: }), commentService.findAll);
  let commentCount = computed(() => comments.value.length);
  let deleteComment = commentId => commentService.delete({ id: commentId });

  return {
// src/components/UserProfile.vue
// ...
import { useUserComments } from '../composables/user-comments';

export default {
  name: 'UserProfile',
  // ...
  setup(props) {
    let { data: user, error } = useSwrv(() =>, userService.find);
    const { commentCount } = useUserComments({ user });

    // ...

In the user-comments Composable, we can encapsulate all the reactive logic to deal with comments. We reactively fetch a user’s comments, and in the example, we also create a computed property for the commentCount. We can reuse this piece of logic everywhere in our application. Most likely in Vue components, but theoretically, we could also run this code in a Node.js environment.

Screenshots of three premium Vue.js templates.

Make Constants and Dependencies Available in the Template

Imagine you need access to a constant or some imported dependency inside the <template> section of your component. When using the Options API, this feels very awkward. You either have to add them to your data option (which can have a significant performance overhead) or use the created hook to add those non-reactive variables to the this context.

Thanks to the Composition API and the setup hook, this feels a lot more natural to do. We can export constants, and dependencies from the setup hook to make them available inside our component’s <template> section.

    <!-- ... -->
    <button @click="create">
    <div>(max. {{ MAX_COMMENTS }} allowed)</div>

import { create } from '../services/comment';

const MAX_COMMENTS = 3;

export default {
  setup() {
    return {

Using the Composition API with Vue 2

If you can’t migrate to Vue 3 today, then you can still use the Composition API already. You can do this by installing the official Composition API Vue 2 Plugin.

Do you want to learn how to build advanced Vue.js applications?

Register for the Newsletter of my upcoming book: Advanced Vue.js Application Architecture.

Do you enjoy reading my blog?

You can buy me a ☕️ on Ko-fi!

☕️ Support Me on Ko-fi