๐Ÿ’š
Websites

Vue 3 Composition API: Writing Clean, Modern Components

16.05.2026
โ† All articles

With the release of Vue 3, developers gained an entirely new way of writing components called the Composition API. This approach was designed to solve the limitations of the Options API that became especially apparent in large and complex applications. If you are used to working with the Options API from Vue 2, the new syntax may feel unfamiliar at first, but after writing just a few components its advantages quickly become clear. In this article we will explore what the Composition API is, which problems it solves, and how to write modern components using practical code examples.

The difference between Options API and Composition API

In the Options API, component logic is divided into several separate sections such as data, methods, computed, and watch. This approach is very convenient for small components because everything has its designated place and the structure is easy to predict. However, as a component grows, a single logical feature such as user search ends up scattered across multiple sections โ€” the data lives in data, the functions in methods, and the watchers in watch. As a result, it becomes difficult to trace related code and maintain it over time.

The Composition API allows you to group logic by feature rather than by option type. All variables, computed values, and watchers belonging to a single concern sit right next to each other in one place. This significantly improves code readability and makes managing large components much easier. In addition, this logic can be extracted into separate files and reused across other components, something that was quite cumbersome with the older approach.

The <script setup> syntax

The most modern and concise way to write components in Vue 3 is the <script setup> syntax. It removes unnecessary boilerplate: you no longer need to write a setup() function, return values explicitly, or manually register components. Every variable and function declared at the top level automatically becomes available in the template, which makes the code noticeably cleaner and shorter.

<script setup>
import { ref } from 'vue'

const count = ref(0)
function increment() {
  count.value++
}
</script>

<template>
  <button @click="increment">Clicked: {{ count }}</button>
</template>

Reactivity: ref, reactive, computed, and watch

The Composition API provides two primary functions for creating reactive state. The ref() function is used for primitive values such as numbers, strings, and booleans, and its value is accessed through the .value property in script, while in the template it is unwrapped automatically. The reactive() function is intended for objects and makes all of their properties reactive. In practice, many developers prefer to use ref everywhere for the sake of consistency.

import { ref, reactive, computed, watch } from 'vue'

const count = ref(0)
const user = reactive({ name: 'John', age: 25 })

// computed โ€” derived value depending on others
const doubled = computed(() => count.value * 2)

// watch โ€” react to changes
watch(count, (newVal, oldVal) => {
  console.log(`Value changed from ${oldVal} to ${newVal}`)
})

The computed() function creates a derived value based on other reactive data and only recalculates when its dependencies change, which is good for performance. The watch() function is used when you need to perform a side effect whenever a value changes โ€” for example, sending an API request or writing to a log. These four functions form the foundation of reactivity in the Composition API and are used in almost every component you write.

Reusing logic with composable functions

The greatest strength of the Composition API is composable functions. A composable is an ordinary function that encapsulates reactive state and logic, typically named with a use prefix. You place logic inside such a function and then call it in any component where it is needed. This mechanism solves the problems of mixins from Vue 2 and keeps your code clean, reusable, and easy to test in isolation.

// useCounter.js
import { ref } from 'vue'

export function useCounter(start = 0) {
  const count = ref(start)
  const increment = () => count.value++
  const reset = () => count.value = start
  return { count, increment, reset }
}

// In a component:
const { count, increment, reset } = useCounter(10)

When to choose which approach

The Composition API is not always the single correct choice. For small and simple components the Options API can still be convenient and very readable, especially if your team has many developers with Vue 2 experience. The Composition API shines most in large components with complex logic, when you need to reuse code, and when working with strong typing through TypeScript. The important thing to understand is that both APIs can be used within the same project, so the transition can be gradual and painless.

In summary, the Composition API is an important step in the evolution of the Vue ecosystem that noticeably simplifies managing large projects and reusing code. With the <script setup> syntax and composable functions you create cleaner, more modular, and more maintainable components. If you are starting a new project, we recommend considering the Composition API as your default choice.

Related articles

๐ŸŒพ Agriculture and Agribusiness Website: Product Catalog and B2B Sales โค๏ธ Charity Foundation Website: Transparent Fundraising and Donor Trust ๐ŸŽ‰ Wedding Venue and Banquet Hall Website: Event Planning and Online Booking ๐Ÿš™ Car Rental Website: Vehicle Catalog, Price Calculator, and Online Booking
๐ŸŒ Language
๐Ÿ‡บ๐Ÿ‡ฟ O'zbek ๐Ÿ‡บ๐Ÿ‡ฟ ะŽะทะฑะตะบ ๐Ÿ‡ท๐Ÿ‡บ ะ ัƒััะบะธะน ๐Ÿ‡ฌ๐Ÿ‡ง English โœ“