The Composition API and script setup
In the Options API, the code for one feature is split across drawers: the reading counter's state in data, its percentage in computed, its button logic in methods. Add a second feature and the drawers mix two stories. The Composition API lets you keep each feature's code together, as plain JavaScript.
The rule
Import the tools, write plain variables and functions, no
this.
The same progress counter, in the Composition API with <script setup>:
<script setup>
import { ref, computed, onMounted } from 'vue'
const props = defineProps({ pages: Number })
const pagesRead = ref(0)
const percent = computed(() => Math.round(pagesRead.value / props.pages * 100))
function addPage() {
pagesRead.value++
}
onMounted(() => console.log('Progress counter is on the page'))
</script>
<template>
<p>{{ pagesRead }} / {{ pages }} ({{ percent }}%)</p>
<button @click="addPage">+1 page</button>
</template>The drawers turned into imported functions:
| Options API | Composition API |
|---|---|
data() |
ref() or reactive() |
computed: {} |
computed(() => ...) |
methods: {} |
ordinary functions |
mounted() |
onMounted(() => ...) |
props: {} |
defineProps() |
<script setup> is the short form. It runs once when each instance is created, and every top-level binding is handed to the template. Without it you would write export default { setup() { ...; return { pagesRead, addPage } } } and list everything by hand.
Because features are plain code, you can lift one out into a function in its own file, often named useSomething, and reuse it in many components:
// useProgress.js
import { ref, computed } from 'vue'
export function useProgress(pages) {
const pagesRead = ref(0)
const percent = computed(() => Math.round(pagesRead.value / pages * 100))
return { pagesRead, percent }
}Such functions are called composables. Both API styles are fully supported in Vue 3; the Composition API is the recommended choice for new projects.
The shortcut
Translating Options to Composition is mechanical: drop this, add .value. Each this.x becomes x.value if x is a ref, or props.x if it is a prop.
Old code
addPage() { this.pagesRead++ }inmethods.
Drills
Answer fast — trust the rule.
In the Composition API, what replaces the data() option?
What does <script setup> save you from writing?
Translate this.pagesRead = 0 (where pagesRead is state) to the Composition API.
What is a composable?
Remember
- The Composition API builds logic from imported functions:
ref,computed,onMounted. - Shortcut: drop
this, add.value. - Trap: reaching for
thisinside<script setup>; it does not refer to the component there.
