Reactivity
State is wrapped in a proxy that tracks every read and notifies every dependent on write. Change the value, and the DOM that used it re-renders itself. You never call setState.
const count = ref(0)
count.value++ // view updates
6 sub-nodes →Single-File Components
One .vue file holds the markup, the logic, and the styles for a component. Styles can be scoped so they never leak. The file is the unit of thinking, not three files in three folders.
<template> … </template>
<script setup> … </script>
<style scoped> … </style>
Templates & Directives
The template is HTML plus a handful of directives. v-if branches, v-for repeats, : binds, @ listens, v-model does two-way binding in one attribute. It compiles to a fast render function.
<li v-for="t in todos" :key="t.id"
@click="toggle(t)">{{ t.text }}</li>Composition API
script setup gives you one flat scope where state, computed values, and lifecycle hooks live together. Pull any group of them into a composable function and reuse the behaviour anywhere.
const double = computed(() => count.value * 2)
onMounted(() => fetchData())
Component Communication
Data flows down through props and back up through emitted events. Slots let a parent pass markup into a child, and provide / inject skips the middle layers when a value is needed deep down.
defineProps<{ label: string }>()
defineEmits<{ save: [id: number] }>()