skip to content

Authoring Style Trade-offs

Options and Composition styles share one reactivity system but organise code by option versus by concern, and infer types differently. Interviewers ask when a team should keep options.

part ofVue.jsoverview, primer and where to startread it →
on this pageshow

explore

questions

5

What is the core difference between Vue 3's Options API and Composition API in how a component's code is organised?

level: juniorimportance: must knowfreq 70%

answer

  1. grouped by kind versus by purpose
  2. data, methods, computed, mounted
  3. one logical concern, many places
  4. same reactivity underneath
  5. options built on composition

basics

~20 s

The Options API groups code by option type (data, methods, computed, lifecycle hooks) on a this-based instance; the Composition API groups it by logical concern in one function scope. Both run on the same reactivity system.

solid answer

~40 s

With the **Options API** you describe a component as an object: state in `data()`, derived values in `computed`, functions in `methods`, side effects in `watch` and hooks such as `mounted`, all reached through `this`. Code for one feature is therefore split across several options. With the **Composition API** you declare state with `ref()` and `reactive()`, derived values with `computed()`, and hooks with `onMounted()` inside `setup()` or `<script setup>`, so everything for one concern can sit together and be extracted into a composable. They are two interfaces to the same system: the docs note that the Options API is implemented on top of the Composition API, so reactivity, lifecycle and rendering behave identically.

code

vue · 20 lines
vue
<script>
export default {
  data() {
    return { query: '', items: [] }
  },
  computed: {
    filtered() {
      return this.items.filter((i) => i.name.includes(this.query))
    }
  },
  methods: {
    async load() {
      this.items = await fetch('/api/items').then((r) => r.json())
    }
  },
  mounted() {
    this.load()
  }
}
</script>

go deeper

for a junior

Recall that options group code by type and composition groups it by concern, and that both share one reactivity system.

for a middle

Explain the scattered-concern problem in large options components and why a concern written with the Composition API can be extracted into a composable.

for a senior

Show that the style changes organisation and reuse only: identical runtime semantics, with structure moving from framework guard rails to author discipline.

for a principal

Frame the style as a codebase-wide convention: which guard rails a team gives up with composition and how it replaces them with its own structure.

## Two interfaces, one system Vue 3 components can be written in two API styles. The **Options API** describes a component as an object of options. The **Composition API** describes it as a function that declares reactive state and effects with imported functions, usually in `<script setup>`. The Vue docs are explicit that these are different interfaces over the *same* underlying system; the Options API is itself implemented on top of the Composition API. Reactivity, the lifecycle, the renderer and templates are shared. ## Options API: organised by option type An Options API component sorts its code into predefined buckets: - `data()` returns the reactive state. - `computed` holds derived values. - `methods` holds functions, bound to the instance. - `watch` holds reactions to changes. - lifecycle options such as `mounted` and `unmounted` hold setup and teardown. Everything is reached through `this`, the component instance. The structure acts as **guard rails**: every piece of code has an obvious place, which is why many developers find the style easy to start with, and why it maps well onto a class-like mental model. ## Composition API: organised by logical concern A Composition API component declares state and effects directly in a function scope: - `ref()` and `reactive()` create state. - `computed()` creates derived values. - plain functions act on state. - `watch()` and `watchEffect()` react to changes. - `onMounted()` and `onUnmounted()` register lifecycle work. Because there are no buckets, the code for one **logical concern**, say "filter the list", can live in one block: its state, its computed value, its watcher and its cleanup. That block can then be moved into a composable with little change. The price is that the structure is the author's responsibility; the docs recommend applying ordinary JavaScript code-organisation practice to it. ## What changes when a component grows The Vue team illustrated the difference with a large folder-explorer component. In its Options API version, code for each concern, such as navigation, favourites or hidden folders, was scattered across `data`, `computed`, `methods` and `watch`, so working on one concern meant scrolling between several places. In the Composition API version, each concern formed a contiguous region that could be extracted as a unit. | Aspect | Options API | Composition API | |---|---|---| | Unit of organisation | option type | logical concern | | Access to state | `this.count` | `count.value` in script, `count` in template | | Lifecycle | `mounted()` option | `onMounted()` call | | Logic reuse | mixins (no longer recommended) | composables | | Structure enforced by | the framework | the author | | Underlying reactivity | shared | shared | ## What does not change 1. **Reactivity semantics**: `data()` state is made reactive with the same machinery as `reactive()`; computed caching and watcher behaviour are the same. 2. **Lifecycle order**: `mounted` and `onMounted()` fire at the same moment; options hooks are registered through the same internal hook registry. 3. **Templates**: the same template syntax works with either style. 4. **Support**: the Options API is not deprecated. The docs call it an integral part of Vue and a solid choice for low-to-medium-complexity scenarios. ## How to phrase it in an interview Say what each style groups by, name one consequence (feature code scattered across options versus kept together and extractable), and stress that both sit on one reactivity system, so choosing a style changes how code is organised and reused, not how Vue behaves at runtime.

  • Does choosing the Composition API change how reactivity or the lifecycle behaves?
    No. Both styles use the same reactivity system and lifecycle; the Options API is implemented on top of the Composition API. `mounted` and `onMounted()` fire at the same point, and `data()` state is made reactive the same way `reactive()` state is. The style changes organisation and reuse, not runtime semantics.
  • Is the Options API deprecated in Vue 3?
    No. The Vue docs say there is no plan to deprecate it, call it an integral part of Vue, and describe it as a solid choice for many low-to-medium-complexity scenarios, while recommending the Composition API with SFCs for full applications.

The Options API is a filing cabinet sorted by document type, with every invoice in one drawer and every letter in another; the Composition API is a folder per project, holding that project's invoices and letters together. Both cabinets hold the same paper.

saying these in an interview costs you the question

  • The Options API is deprecated in Vue 3 and kept only for compatibility.
  • The two styles use different reactivity systems with different behaviour.
  • The Composition API is simply the Options API with renamed functions.
  • Composition API components cannot use templates and need render functions.
  • Code organisation is automatic in the Composition API, just as in options.
open as a page

Can a Vue 3 component use the Options API and the Composition API together, and what rules govern that mix?

level: middleimportance: should knowfreq 45%

basics

~10 s

Yes, through the setup() option: it runs before every options hook, and what it returns is available on this to options; setup() cannot read options, and <script setup> bindings never reach the Options API.

open as a page

Why does TypeScript inference work more naturally with Vue 3's Composition API than with the Options API?

level: middleimportance: should knowfreq 40%

basics

~20 s

Composition API code is plain variables and functions whose types TypeScript infers directly; the Options API needs defineComponent and complex types to rebuild this from several options, and inference still breaks down for mixins and injection.

open as a page

Your team maintains a large Vue 3 Options API codebase; how do you decide whether to migrate it to the Composition API?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Migrate only where it pays: the Options API is not deprecated, so convert components whose concerns are tangled, whose mixins leak or whose typing hurts, write new code with the Composition API, and bridge with setup() meanwhile.

open as a page

As lead of a new Vue 3 application with a mixed-experience team, how would you choose between the Options API and the Composition API?

level: principalimportance: should knowfreq 30%

basics

~20 s

For a full application built with SFCs, choose the Composition API with <script setup>, as the Vue docs recommend, and offset its missing guard rails with written conventions, composable patterns and review; reserve the Options API for build-less or low-complexity work.

open as a page