Options API vs Composition API

Beginner
12 min

Options API vs Composition API

Vue 3 lets you write a component in two styles. The Options API organizes code into option objects (data, methods, computed), while the Composition API organizes code by feature using imported functions such as ref and computed. After this lesson you will be able to read both styles, translate between them and choose the right one for a project.

The Options API

In the Options API a component is an object whose keys are fixed option names. Reactive state lives in data(), functions in methods, derived values in computed, and everything is accessed through this:

vue
<script> export default { data() { return { count: 0 } }, computed: { double() { return this.count * 2 } }, methods: { increment() { this.count++ } }, mounted() { console.log('mounted with', this.count) } } </script> <template> <button @click="increment">{{ count }} (double: {{ double }})</button> </template>

data must be a function that returns a fresh object, so every component instance gets its own copy of the state. Lifecycle hooks (created, mounted, updated, unmounted) are options too.

The Same Component with the Composition API

With <script setup> there are no option buckets. You import what you need and declare plain variables and functions:

vue
<script setup> import { ref, computed, onMounted } from 'vue' const count = ref(0) const double = computed(() => count.value * 2) function increment() { count.value++ } onMounted(() => console.log('mounted with', count.value)) </script> <template> <button @click="increment">{{ count }} (double: {{ double }})</button> </template>

Two things differ visibly. There is no this; you reference count directly. And a ref is unwrapped in the template ({{ count }}), but in script you read and write count.value.

Mapping Between the Two Styles

| Options API | Composition API | | --- | --- | | data() | ref(), reactive() | | computed: {} | computed() | | methods: {} | plain functions | | watch: {} | watch(), watchEffect() | | mounted() | onMounted() | | beforeUnmount() | onBeforeUnmount() | | props option | defineProps() | | emits option | defineEmits() | | mixins | composables | | this.$refs.x | template refs via useTemplateRef('x') |

Note that created and beforeCreate have no Composition API equivalent: code placed directly inside <script setup> runs at that point.

Why the Composition API Is Preferred

The Options API is easy to learn because it tells you where to put things. Its weakness shows in large components: the logic for one feature (say, fetching and filtering a list) is scattered across data, computed, methods and mounted. The Composition API keeps that logic together and lets you extract it into a reusable function called a composable:

javascript
// useCounter.js import { ref, computed } from 'vue' export function useCounter(start = 0) { const count = ref(start) const double = computed(() => count.value * 2) const increment = () => count.value++ return { count, double, increment } }

Any component can now call const { count, increment } = useCounter(10). Mixins, the Options API equivalent, suffer from unclear property sources and naming collisions, which composables avoid. The Composition API also gives far better TypeScript inference, which is why the official documentation defaults to it.

When You Will Still Meet the Options API

  • Existing codebases written for Vue 2 or early Vue 3.
  • Small, simple components where the option layout reads clearly.
  • Documentation, tutorials and answers written before <script setup> became the default.

Both styles are fully supported and can be mixed in one project. You can even use a setup() function inside an Options API component to adopt the Composition API gradually.

Common mistakes

  • Forgetting .value in script when reading a ref: if (count > 5) compares the ref object, not the number.
  • Using arrow functions for Options API methods: increment: () => this.count++ has the wrong this.
  • Destructuring reactive() objects or props, which loses reactivity (covered in the reactivity lesson).
Quick Quiz
Question 1 of 2

In the Composition API, how do you read the current value of `const count = ref(0)` inside `<script setup>`?

Key Takeaways

  • The Options API groups code by option type (data, methods, computed) and uses this.
  • The Composition API groups code by feature using ref, computed, watch and lifecycle functions.
  • <script setup> is the recommended way to write Composition API components.
  • Composables replace mixins for sharing logic and offer better TypeScript support.
  • Both styles are supported in Vue 3 and can coexist in the same project.

Next lesson: Directives: v-if, v-for, v-bind, v-model — the built-in template directives that control rendering, attributes and two-way binding.

Options API vs Composition API - Vue.js | CodeYourCraft | CodeYourCraft