What is Composition API? Explain the difference between Options API [Vue.jsOfficial Partner]

In September 2020, Vue.js released its version 3 series.

The most notable feature of the version 3 series is arguably the introduction of the “Composition API.”

The Composition API is a new format for Vue components, and its implementation and syntax differ significantly from the Options API format, which was the standard in the version 2 series.

In this article, the editorial team of Skilled, a front-end specialized programming learning tool, will clearly explain what the Composition API is and how it differs from the Options API.

 

What is the Composition API?


The Composition API is a format for components that allows you to separate and handle reactive values and processes related to those values from the component itself.

With the Composition API, you can create components using imported functions.

Understanding the features of the Composition API is easier when looking at the issues with the Options API format, which was the traditional component format in Vue.js.

We will look at the issues with the Options API and compare

Problems with the Options API (Traditional Vue)

Below is the script block for a counter app written in the Options API.

export default {
  data: () => ({
    count: 0,
  }),
  methods: {
    add() {
      this.count++;
    },
    reduce() {
      this.count--;
    },
    doubleUp() {
      this.count = this.count * 2;
    },
    reset() {
      this.count = 0;
    },
  },
};

If you have used Vue.js before, you’ll find this script block familiar.

The issues with this Options API format include:

  • You have to go through ‘this’ to access reactive values, making it impossible to separate the processing in ‘methods’ from the Component’s View.
  • Related elements become scattered.

There are often times when you want to separate and reuse the logic in the ‘methods’ section, but if you are accessing reactive values, you generally can’t separate it from the view. This was a problem with the Options API.

Because you can’t separate it, when you create complex components, you end up with a bloated structure where just the script block alone can be several hundred lines long.

Another issue is that related elements become scattered.

For example, let’s say an element called ‘member’ is added to the above code, and computed properties for adding, deleting, and sorting members are also added.

Options APIの実装例

In the Options API, you add elements to each option property like data, methods, and computed.

As a result, it’s difficult to group related elements together. The structure becomes scattered as shown below, and as the component becomes more complex, readability suffers.

Options API 関連要素の色分け

Drawbacks of Mixins

In the Options API, you can use the mixin feature to bundle and reuse elements like data and methods.

However, there are several drawbacks to using mixins:

  • Ambiguous Elements: When using multiple mixins, it becomes unclear which instances within the component are added by the mixins.
    ➝ In the Composition API, reactive values are managed independently of the view through refs, making the source of properties clear.
  • Namespace Conflicts: When using multiple mixins, there’s a possibility of registering duplicate property keys.
    ➝ In the Composition API, if there are conflicting keys, you can change the name of the destructured variables.
  • Mixin’s ‘this’ is not Loosely Coupled: The ‘this’ in mixins refers to the component, making it not loosely coupled. You need to design with the component dependencies in mind.

These drawbacks are also mentioned in the official documentation, and the use of mixins is discouraged from Vue 3 onwards.

Solving with the Composition API

Next, let’s write the script block with the same behavior using the Composition API.

The Composition API has a feature called Composition Functions.

This feature allows you to extract the component’s logic without depending on the View.

Using this feature, you can separate the elements used in the counter and the elements used in the member, and define them in separate files.

useCounter.ts useMember.ts

As shown above, encapsulating stateful logic using the Composition API is called “Composable.”

Composables can be easily invoked by importing them.

The component called from App.vue by importing it will look like this.

Composition API コンポーネントCompared to the Options API, you can describe the elements of logic without scattering them.

Compostion API コンポーネント 関連要素

One of the features of the Composition API is that by dividing and managing elements, you can create components with high readability without scattering related elements.

 

How to Use the Composition API


Here, we will explain how to use the Composition API while comparing it with the Options API.

We will introduce how to rewrite it compared to the properties of the Options API.

data

Options API

data: () => ({
  count: 0,
}),

Composition API

import { ref } from "vue"
 
const count = ref(0);

In the Options API, reactive values were defined using the data option, but in the Composition API, you define and use the ref and reactive functions.

There are the following differences between ref and reactive:

  • ref ➝ Directly accessible (for primitive types)
  • reactive ➝ Accessed like an object using a “.” (dot)

methods

Options API

methods: {
    addCounter() {
      this.count++;
    },
  },

Composition API

const addCounter = () => {
  count.value++;
};

In the Options API, you defined them within the methods option, but in the Composition API, you can simply define functions within the script block to call them.

A significant change is the specification for modifying reactive values.

To change a reactive value defined with ref, you use `.value`.

count.value++;

In this example, we are changing the value of the `count` variable by accessing and modifying its `value`.

computed

When using `computed`, you define it using the `computed` function.

Options API

data: () => ({
    count: 1,
  }),
  computed: {
    doubleCount() {
      return count * 2;
    },
  },

Composition API

import { ref, computed } from "vue";
 
const count = ref(0);
const doubleCount = computed(() => {
return count.value * 2;
});

In the Composition API, `computed` is defined using the `computed` function.

The specifications for `computed` are the same as in the Options API; you cannot directly modify the value of `computed`.

props

In the Options API, `props` were defined using the `props` property.

In the Composition API, you define `props` using the `defineProps` function.

Options API

props: {
    count: {
      type: Number,
      required: true,
    },
  },

Composition API

import { ref } from "vue";

const props = defineProps({
  count: { type: Number, required: true },
});

Additionally, in a TypeScript environment, strict type definitions are possible.

props: { count: { type?: number, }, },

watch

In the Composition API, you can use the `watch` function to monitor reactive values in the same way as in the Options API.

Options API

watch: {
    count(count, oldCount) {
      console.log(count);
      console.log(oldCount);
    },
  },

Composition API

import { ref, watch } from "vue";
const count = ref(0);
watch(count, (count, oldCOunt) => {
  console.log(count);
  console.log(oldCOunt);
});

 

Using Lifecycle Methods


In the Composition API, you can use lifecycle methods in the same way as in the Options API.

However, be cautious as some method names have been changed compared to the Options API.

The lifecycle methods in the Composition API corresponding to those in the Options API are as follows.

Options API setup 内のフック
beforeCreate Not needed*
beforeMount onBeforeMount
beforeUpdate onBeforeUpdate
beforeUpdate onUnmounted
beforeUpdate onErrorCaptured
renderTracked onRenderTracked
renderTriggered onRenderTriggered
activated onActivated
onBeforeMount onDeactivated

You can use them by importing each function.

import { onMounted } from "vue";
onMounted(() => {
  console.log("onMounted");
});

The above is an example using `onMounted`, but other methods can also be used if you import and define them.

About Provide / Inject


We will also explain about `provide` and `inject`, which are closely related to the Composition API.

Even with the Composition API, you cannot share reactive values between multiple components just by extracting logic and state.

For example, even if you import and use the same `useCounter` composable in two components, `useCounter` is generated in each component, so information cannot be shared between components.

This is where `Provider` comes in.

Below is an example of implementing `Provider`.

useCouter.tsProvider 設定

In Composables, you define a key using `InjectionKey` for referencing.

Next, you provide it in the parent component.

By doing this, you enable even deeply nested child components to share the state of `useCounter`.

App.vue親コンポーネント Provider設定

In child components, you can use `inject` to access what was provided in the parent component.

子コンポーネント Provider設定

With this, values updated in the parent component are also conveyed to the child component, enabling sharing between parent and child.

Summary


With Vue.js’s Composition API, it has become easier to “extract and reuse logic.”

In complex applications where components become bloated, you can create components that are easy to read and maintain by separating the logic.

Also, just because the Composition API was developed doesn’t mean that the Options API has become deprecated in Vue 3.

The official documentation clearly states that there are no plans to deprecate the Options API.

Will Options API be deprecated?

While the Composition API offers a high degree of freedom, it is also a feature that is difficult to leverage without considering design and architecture, so thorough consideration is needed when introducing it.

We have introduced the Composition API.

Learn Vue.js with Skilled


Skilled is a practice-focused programming learning service. We are also an official partner of Vue.js, offering services where you can learn Vue.js.

To maximize your learning efficiency and convert it into skills, we are inventing various technologies related to learning, including patented technologies.

We cover learning from markup to application engineering, and by coding while learning practically, you can acquire “skills” rather than just knowledge.

We are currently running a free trial campaign, so if you are interested, please feel free to take advantage of the free trial.

Click here for a free trial of Skilled.