Vue 3 with <script setup> is a genuinely excellent framework in 2026 — reactive primitives, excellent TypeScript support, and a progressive enhancement model that works from a single script tag up to a full Nuxt 4 app. The catch: the learning path is cluttered with Options API tutorials that waste your time. This guide skips them.
What changed in 2026
- Vue 3.5+ performance improvements — the reactivity system was rewritten for lower memory usage;
watchEffect behavior is more predictable.
- Nuxt 4 is stable — file-based routing, server components, and edge rendering make it the default for new Vue projects that need a backend.
- Vapor mode (experimental) — a compile-time rendering mode that removes the virtual DOM entirely; opt-in per component.
- Vite 6 is the standard build tool for Vue; create-vue scaffolds with it by default.
- Pinia 3 adds better TypeScript inference and a
storeToRefs DX improvement.
Setting up your first project
npm create vue@latest my-app
cd my-app
npm install
npm run dev
Answer Yes to TypeScript, Vue Router, and Pinia when prompted. That's your production scaffold.
Core concepts in order
1. Reactivity with ref and computed
<script setup lang="ts">
import { ref, computed } from "vue";
const count = ref(0);
const doubled = computed(() => count.value * 2);
function increment() {
count.value++;
}
</script>
<template>
<button @click="increment">Count: {{ count }} (doubled: {{ doubled }})</button>
</template>
The .value wrapper in <script> is intentional — it makes reactivity explicit. Templates unwrap ref automatically.
2. Props, emits, and component communication
<script setup lang="ts">
const props = defineProps<{ title: string; count: number }>();
const emit = defineEmits<{ update: [value: number] }>();
</script>
defineProps and defineEmits are compiler macros — no imports needed in <script setup>.
3. Composables (the Composition API power move)
// composables/useCounter.ts
import { ref } from "vue";
export function useCounter(initial = 0) {
const count = ref(initial);
const increment = () => count.value++;
const reset = () => (count.value = initial);
return { count, increment, reset };
}
Composables replace mixins entirely. Any stateful logic you want to share goes here.
Comparison: Vue vs other frameworks in 2026
| Dimension |
Vue 3 |
React 19 |
Svelte 5 |
Angular 19 |
| Learning curve |
Low–Medium |
Medium |
Low |
High |
| TypeScript DX |
Excellent |
Excellent |
Good |
Excellent |
| SSR story |
Nuxt 4 |
Next.js |
SvelteKit |
Angular SSR |
| Bundle size |
Small |
Medium |
Very small |
Large |
| Job market |
Large |
Very large |
Small |
Large |
Vue's learning curve is genuinely lower than React's. If you are already React-native, the gap is smaller.
How to pick the right Vue track
- Building a content site / blog / marketing page → Nuxt 4 with SSR or SSG.
- Building a SPA / dashboard → Vite + Vue Router + Pinia.
- Embedding Vue into an existing server-rendered app → Progressive enhancement with the CDN build.
- Full-stack with an API → Nuxt 4 with server routes (replaces a separate Express layer).
State management in 2026
Pinia is the answer. Do not install Vuex.
// stores/user.ts
import { defineStore } from "pinia";
import { ref, computed } from "vue";
export const useUserStore = defineStore("user", () => {
const name = ref("");
const isLoggedIn = computed(() => name.value.length > 0);
function login(n: string) { name.value = n; }
return { name, isLoggedIn, login };
});
Common mistakes
Using Options API examples from older tutorials. They work but train you to write code nobody on a modern team wants to review.
Forgetting .value in <script>. Vue warns you, but understanding why .value exists (tracking dependencies) matters for debugging.
Putting everything in one mega-store. Each domain gets its own Pinia store. One useAppStore for everything is an anti-pattern.
Skipping defineEmits types. TypeScript in templates is only as good as your emit declarations.
What to skip
- Vue 2 — end of life; do not start new projects on it.
- Vuex — replaced by Pinia; no reason to learn it for new code.
vue-class-component — a decorator-based API nobody uses for new projects.
FAQ
Is Vue or React better for getting a job in 2026?
React has a larger job market globally. Vue is strong in China and parts of Europe. Both teach transferable component-model skills.
Do I need to learn Vue Router if I use Nuxt?
Nuxt's file router builds on Vue Router internally. Understanding Vue Router fundamentals helps when you need to configure guards or named routes.
When should I use reactive instead of ref?
Use reactive when you have a tightly coupled group of related state values that you always use together. Otherwise ref is simpler.
Can Vue components use JSX?
Yes — Vue supports JSX/TSX via the @vitejs/plugin-vue-jsx package. Most teams stick with SFCs; JSX is mainly useful for render-function-heavy libraries.
Where to go next