Skip to the solution
MediumFrontend10 min read

What is the Composition API and how does it differ from the Options API?

182 views

The problem

Question presented to candidate: "Our codebase has older Vue components written with data, methods and computed, and newer ones using <script setup>. Explain what the Composition API is, how it differs from the Options API, and which one you would pick for new code."

What a strong answer should cover:

  • The Options API organises a component by option type (data, computed, watch, methods, lifecycle options) and reaches state through this.
  • The Composition API organises it by feature: ref, reactive, computed, watch and onMounted are imported functions called inside setup() or <script setup>.
  • Both sit on the same reactivity system; the Options API is implemented on top of it, so they are equally capable and can be mixed in one component.
  • The real wins are logic reuse through composables, better TypeScript inference (no this), and code that groups by concern in large components.
  • Trade-offs: the Options API is more guided for beginners; the Composition API needs discipline (.value, organising code yourself).
  • A build can drop the Options API code with the __VUE_OPTIONS_API__ flag when no component uses it.

Clarifying questions expected:

  • "Is this for new components only, or are we considering migrating existing ones?"
  • "Do we use TypeScript? That changes how strong the case is."

Code / implementation expected: Optional β€” the same small feature in both styles, ideally showing this versus ref and .value.

  • composition-api
  • options-api

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

10 min read Β· 12 sections

Read the code

VueThe same counter written with the Options API and the Composition API
<script setup>
import { ref, computed, watch, onMounted, h, defineComponent } from "vue";

// ── Options API: the same feature split across data / computed / watch / methods / mounted
const OptionsCounter = defineComponent({
  name: "OptionsCounter",
  data() {
    return { count: 0, log: [] };
  },
  computed: {
    double() { return this.count * 2; },
  },
  watch: {
    count(now, before) { this.log.push(`${before}->${now}`); },
  },
  methods: {
    inc() { this.count++; },
  },
  mounted() { console.log("[options] mounted, this.count =", this.count); },
  render() {
    return h("div", { class: "box" }, [
      h("button", { id: "opt", onClick: this.inc }, "Options +1"),
      h("p", `count ${this.count}, double ${this.double}, log [${this.log.join(", ")}]`),
    ]);
  },
});

// ── Composition API: the same feature as one block of plain functions
const count = ref(0);
const log = ref([]);
const double = computed(() => count.value * 2);
watch(count, (now, before) => log.value.push(`${before}->${now}`));
const inc = () => count.value++;
onMounted(() => console.log("[composition] mounted, count.value =", count.value));
</script>

<template>
  <OptionsCounter />
  <div class="box">
    <button id="comp" @click="inc">Composition +1</button>
    <p>count {{ count }}, double {{ double }}, log [{{ log.join(", ") }}]</p>
  </div>
</template>
VueMixing both styles: setup() return values are visible to Options API code
<script>
import { ref } from "vue";
export default {
  setup() {
    console.log("inside setup(), this is", this);
    const fromSetup = ref("hello");
    return { fromSetup };
  },
  data() { return { fromData: "world" }; },
  mounted() { console.log("mounted() sees", this.fromSetup, this.fromData); },
};
</script>
<template><p>{{ fromSetup }} {{ fromData }}</p></template>

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 66 of 92 in Vue.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Vue.js questions
Up nextMedium

What is nextTick in Vue?

Continue