Feladatból indulsz, működő kódot másolsz ki. Egy közös példán, egy teendőlistán át, a hivatalos dokumentáció ajánlott útján: Composition API és <script setup>.
Vue
3.5.43, stabil 2026. szeptember 17.
Stílus
Composition API, <script setup>
Indítás
npm create vue@latestVite
Ellenőrizve
/
20 recept és 11 hiba az oldalon.
Feladatra, direktívára vagy a konzol hibaüzenetére is kereshetsz. Enter: ugrás a legjobb találatra, Esc: törlés.
01
Indulás
Üres gépről futó projektig, hat lépésben.
Node.js telepítése
A Vue fejlesztőeszközei -en futnak. A projektgenerátor (create-vue 3.24) a 22.18-as vagy újabb 22-es, illetve a 24.12-es vagy újabb Node-ot kéri. Letöltés: nodejs.org (új lapon nyílik). Ellenőrzés a terminálban:
Terminál
node -v
Projekt létrehozása
A hivatalos generátor egy -alapú projektet készít. A @latest nem hagyható el, különben az npm egy régi, gyorsítótárazott változatot is futtathat. A varázsló a projekt nevét és a kiegészítőket kérdezi (pl. TypeScript, Router, Pinia, ESLint); kezdéshez mindenre mehet a „Nem”, később bármelyik hozzáadható.
Terminál
npm create vue@latest
Indítás
Belépsz a mappába, telepíted a függőségeket, és elindítod a fejlesztői szervert. A Vite kiírja a címet (alapból http://localhost:5173); mentéskor a böngésző azonnal frissül. A kész, feltölthető oldalt az npm run build teszi a dist mappába.
Terminál
cd teendolista
npm install
npm run dev
Mi van a mappában?
A fontosabb fájlok. A saját kódod szinte mind az src mappába kerül: a App.vue-ba és a components alá. A projektet érdemes rögtön Gitbe tenni: a lépéseket a Git-kézikönyv mutatja.
teendolista/
teendolista/
├─ index.html egy üres <div id="app">
├─ package.json függőségek és parancsok
├─ vite.config.js a Vite beállításai
├─ public/ változatlanul kimásolt fájlok
└─ src/
├─ main.js itt indul az alkalmazás
├─ App.vue a gyökérkomponens
├─ assets/ képek, CSS
└─ components/ a saját komponenseid
Egy .vue fájl három része
Egy .vue fájl egy : a <script setup> a logika, a <template> a HTML, a <style scoped> a csak erre a komponensre ható CSS. A setup miatt a scriptben létrehozott változókat és importokat a sablon közvetlenül látja.
A main.js létrehozza az alkalmazást az App.vue-ból, és beleteszi az index.html üres #app elemébe. A generátor ezt megírja, általában nem kell hozzányúlni.
src/main.js
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
Minden recept egy feladat. A példák ugyanarra a teendőlistára épülnek, és kimásolva futnak.
Adat
Hol él az állapot, és mitől frissül az oldal.
Adatot tárolni, ami frissíti az oldalt
ref()
A ref() egy doboz. Ha a tartalma megváltozik, a Vue frissíti az oldal azon részeit, ahol használod. Sima JS-ben ehhez textContent-et írnál át kézzel. Ez a adat.
Scriptben darab.value, a sablonban csak darab. A const nem gond: a doboz marad ugyanaz, csak a tartalma változik. Ha elmarad a .value
Szamlalo.vue
<script setup>
import { ref } from 'vue'
const darab = ref(0)
function novel() {
darab.value++
}
</script>
<template>
<button @click="novel">Kattintások: {{ darab }}</button>
</template>
Összetartozó adatokat egy objektumban tartani
reactive()
A reactive() egy objektumot tesz reaktívvá, és nem kell hozzá .value. Két korlátja van: az egész objektumot nem cserélheted le, és ha szétszeded (destrukturálod), a darabok már nem frissülnek. Kezdőként a ref elég mindenre, objektumra is.
Ha egy érték kiszámolható más adatokból (szűrt lista, összeg, teljes név), ne tárold külön. A computed() megjegyzi az eredményt, és csak akkor számol újra, ha a forrás változik. Csak olvasásra való: ne írj benne más adatot.
Sablonban: {{ hatralevo.length }} teendő van hátra. Scriptben itt is hatralevo.value.
A watch() egy adatot figyel, és változáskor lefuttat egy függvényt. való: mentés, szerverhívás, címsor átírása. Ha csak egy értéket akarsz kiszámolni, az computed. A watchEffect() azonnal lefut, és magától figyel mindent, amit olvas.
Objektum egy mezőjét függvénnyel figyeld: watch(() => urlap.szoveg, …). Belső változásokhoz: { deep: true }, azonnali első futáshoz: { immediate: true }.
Attribútumba a {{ }} nem működik, oda a v-bind kell, röviden kettőspont. Kettősponttal az idézőjelben JS-kifejezés van: src="kep" a „kep” szöveg, :src="kep" a kep változó értéke.
Ha a változó neve egyezik az attribútuméval, elég a rövid alak: :id ugyanaz, mint :id="id" (Vue 3.4 óta).
Ugyanaz, mint az addEventListener, csak a sablonban. A v-on rövidítése a @. Utána az esemény neve, majd módosítók: .prevent (nem tölti újra az oldalt), .stop, .once, billentyűk: .enter, .esc.
Paraméterrel: @click="torol(teendo.id)". Az eseményobjektum ilyenkor $event néven érhető el.
Mint az if / else if / else, csak elemekre. Hamis feltételnél az elem be sem kerül a DOM-ba. A v-show az elemet megtartja, csak elrejti (display: none): gyakori ki-be kapcsolgatásnál ez a jobb.
Egy elemből annyi példányt rajzol, ahány eleme a tömbnek van. A :key minden elemnek egyedi, állandó azonosító (pl. id): ebből tudja a Vue, melyik sor melyik, ha a lista változik. Számtartományhoz: v-for="n in 5" (1-től 5-ig).
Indexet csak akkor használj kulcsnak, ha a lista soha nem rendeződik át. Szűréshez ne tedd a v-if-et ugyanarra az elemre. Miért?
Összeköt egy mezőt egy ref-fel, mindkét irányba: amit beírnak, bekerül a változóba, és ha a változót írod át, a mező is követi. Módosítók: .trim (szóközök le), .number (számmá alakít), .lazy (csak mezőelhagyáskor frissít).
Egy .vue fájl egy . Másikban úgy használod, hogy a <script setup>-ban importálod, és a sablonban leírod a nevét, mint egy HTML-elemet. Regisztrálni nem kell.
A szülő úgy ad adatot a gyereknek, mint egy HTML-attribútumot. A gyerek a defineProps()-szal mondja meg, mit vár. Vue 3.5 óta szét is szedheted, és az alapértéket ott adhatod meg; a darabok reaktívak maradnak. A gyerek a propot csak olvassa.
Szétszedett propot függvénnyel figyelj: watch(() => szoveg, …). 3.5 előtt: const props = defineProps(…), majd props.szoveg. Átírnád a propot?
<TeendoElem
v-for="teendo in teendok"
:key="teendo.id"
:szoveg="teendo.szoveg"
:kesz="teendo.kesz"
/>
Szólni a szülőnek, hogy történt valami
defineEmits()
Visszafelé a gyerek eseményt küld, a szülő pedig @-cal figyeli, mint egy kattintást, csak saját névvel. Az esemény mellé adatot is küldhetsz: emit('atnevezes', ujNev), a szülő ezt paraméterként kapja.
<TeendoElem
v-for="teendo in teendok"
:key="teendo.id"
:szoveg="teendo.szoveg"
@torles="torol(teendo.id)"
/>
v-model a saját komponensen
defineModel()
A defineModel() egy refet ad, ami a szülő v-model-jéhez kötődik: olvasva a szülő értékét kapod, írva visszaküldöd. Enélkül külön prop és emit kellene. Vue 3.4 óta van.
Több is lehet névvel: defineModel('kesz') a gyerekben, v-model:kesz="…" a szülőben.
Amit a komponens címkéi közé írsz, az a <slot> helyére kerül. Keretekhez, kártyákhoz, felugró ablakokhoz való. Több helyhez nevet adsz, és a szülő <template #nev>-vel tölti ki.
A <slot> tartalma az alapérték: akkor látszik, ha a szülő nem ad semmit.
Ha egy adatot öt szinten át kellene propként továbbadni, a felső komponens provide()-dal kínálja, bármelyik leszármazott inject()-tel kéri. Refet adj át, így a változás lent is látszik.
Az egész alkalmazás közös állapotához a hivatalos megoldás a Pinia.
App.vue · script
import { ref, provide } from 'vue'
const tema = ref('sotet')
provide('tema', tema)
Gomb.vue · script
import { inject } from 'vue'
const tema = inject('tema')
Életciklus és újrahasznosítás
Mikor fut a kód, hogyan éred el a DOM-ot, hogyan szervezed ki.
Adatot betölteni, amikor a komponens megjelenik
onMounted()
Az onMounted() akkor fut, amikor a komponens már az oldalon van. Ez az egyik pontja. Betöltésnél három állapotot kezelj: tölt, kész, hiba.
Takarításhoz (időzítő, eseményfigyelő) az onUnmounted() való. A horgot mindig a script tetején, szinkron hívd. Miért?
Ha magát az elemet kell elérned (fókusz, görgetés, méret), adj neki ref="nev" attribútumot, és kérd el a useTemplateRef('nev')-vel. Az értéke csak megjelenés után van meg, előtte null. Vue 3.5 óta van.
3.5 előtt: const mezo = ref(null), és a sablonban ref="mezo", ugyanazzal a névvel.
A egy sima függvény, ami Vue-s reaktivitást használ, és use-zal kezdődik a neve. Ez itt a listát a böngésző tárhelyére menti, és bármelyik komponensben egy sorral használható.
A composable-t is a script tetején, szinkron hívd, ugyanúgy, mint az onMounted-et.
Erre nincs recept. Próbáld a direktíva nevével (pl. v-for), vagy nézd meg a hibákat.
03
Gyakori hibák
A konzol üzenete angolul, szó szerint, ahogy a Vue 3.5 kiírja; mellette, hogy mit jelent, és hogyan javítsd. Az üzenetet a fenti keresőbe is bemásolhatod.
Elmarad a .value a scriptben
ref()
Üzenet
Nincs: csendben hibás az eredmény.
A ref egy doboz, nem maga a szám. A darab++ a dobozt írná felül, ami const-nál hiba (a fordító vagy a böngésző szól). A darab > 5 pedig a dobozt hasonlítja, ezért mindig hamis, Vue-üzenet nélkül.
RosszSzamlalo.vue
const darab = ref(0)
function novel() {
darab++
}
if (darab > 5) console.log('sok')
JóSzamlalo.vue
const darab = ref(0)
function novel() {
darab.value++
}
if (darab.value > 5) console.log('sok')
Üres marad a kiírás: .value a sablonban
{{ }}
Üzenet
Nincs: csendben hibás az eredmény.
A sablonban a Vue a felső szintű refeket magától kibontja. A darab.value ott már a szám .value-ja, vagyis undefined, ezért üres. Kivétel: ha a ref egy sima objektum mezőjében van, azt nem bontja ki.
RosszSzamlalo.vue
<template>
<p>{{ darab.value }}</p>
</template>
JóSzamlalo.vue
<template>
<p>{{ darab }}</p>
</template>
Szám vagy változó helyett szöveg megy át
v-bind :
Üzenet[Vue warn]: Invalid prop: type check failed for prop "db". Expected Number with value 3, got String with value "3".
Kettőspont nélkül az idézőjelben sima szöveg van: db="3" a „3” sztring, src="kep" a „kep” szó. Kettősponttal JS-kifejezés: szám, változó, logikai érték.
ÜzenetElements in iteration expect to have 'v-bind:key' directives.[Vue warn]: Duplicate keys found during update: 1 Make sure keys are unique.
Az első az ESLint (eslint-plugin-vue) üzenete, a második a Vue-é.
A kulcsból tudja a Vue, melyik sor melyik, amikor a lista változik. Hiányzó vagy ismétlődő kulcsnál rossz sor kaphatja meg a mező tartalmát vagy az animációt. Kulcs legyen egyedi és állandó, pl. id.
Üzenet[Vue warn]: Property "teendo" was accessed during render but is not defined on instance.
A Vue 3-ban a v-if fut előbb, amikor a teendo még nem létezik. (A Vue 2-ben fordítva volt, ezért régi példákban még látni.) Szűrj egy computed-del, és azon menj végig.
Üzenet[Vue warn]: Failed to resolve component: TeendoElem If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.
A sablonban használt nevet a Vue nem találja: elmaradt az import, el van írva, vagy rossz az útvonal. A <script setup>-ban az import egyben a regisztráció is.
Üzenet[Vue warn]: onMounted is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup(). If you are using async setup(), make sure to register lifecycle hooks before the first await statement.
Az onMounted és a többi horog (és az ezeket hívó composable) csak a komponens felállítása közben regisztrálható: a <script setup> tetején, szinkron. Eseménykezelőben, időzítőben vagy saját async függvényben egy await után már nincs „aktív komponens”.
RosszUjTeendo.vue · script
import { onMounted } from 'vue'
function megnyit() {
onMounted(() => {
mezo.value.focus()
})
}
Tutorialban, régi projektben még gyakori az Options API és a Vue 2. Az Options API a Vue 3-ban is teljes értékű; a hivatalos útmutató teljes alkalmazáshoz a Composition API-t és az egyfájlos komponenst ajánlja, ezért ez az oldal azt tanítja. A Vue 2 életciklusa 2023. december 31-én véget ért.
Options API
A Vue 3-ban is működik, csak más stílus. Ha Composition API-ra írod át:
Konzolüzenetek: szó szerint a vue 3.5.43 forrásából (@vue/runtime-core, @vue/reactivity, @vue/compiler-core, @vue/compiler-sfc), github.com/vuejs/core (új lapon nyílik), MIT-licenc; az ESLint-üzenet az eslint-plugin-vue 10.11.1-ből, MIT-licenc.
Verziók: az npm-tárház adatai (vue 3.5.43, 2026. szeptember 17.; a 3.6 ekkor még kiadásra jelölt), a Node-igény a create-vue 3.24.0 csomagból, a Vue 2 életciklusának vége a v2.vuejs.org/eol (új lapon nyílik) oldalról. Ellenőrizve: 2026. október 12.
A Vue.js a jogosultja védjegye; az oldal nem áll kapcsolatban vele. A kereső és a másolás a böngésződben fut, az oldal semmit nem ment és nem küld el.
Reaktív
Olyan adat, amelyet a Vue figyel. Ha megváltozik, a Vue magától frissíti az oldalon azokat a helyeket, ahol használod.
SFC (egyfájlos komponens)
Single-File Component: egy .vue fájl, amelyben a komponens HTML-je, JS-e és CSS-e együtt van.
Direktíva
A Vue saját attribútuma, v- előtaggal (vagy rövidítve :, @, #). Megmondja, mit csináljon a Vue az elemmel.
Kifejezés
JavaScript, aminek értéke van: 2 + 3, nev.toUpperCase(), kesz ? 'igen' : 'nem'. Az if, a let és a for utasítás, nem kifejezés.
Vite
Fejlesztőeszköz: helyi szervert indít, a mentett változást azonnal megmutatja a böngészőben, és a kész oldalt is ez építi (npm run build).
Node.js
JavaScript-futtató a böngészőn kívül. A Vue fejlesztőeszközei (npm, Vite) ezen futnak; a kész oldalhoz nem kell.
Komponens
Önálló, újrahasználható darab az oldalból, saját sablonnal, logikával és stílussal. Mintha saját HTML-elemet írnál.
Mellékhatás
Olyan művelet, ami nem csak értéket számol: mentés, szerverhívás, konzolra írás, a címsor átírása.
Életciklus
A komponens élete: létrejön, megjelenik az oldalon (onMounted), frissül (onUpdated), eltűnik (onUnmounted). Ezekhez a pontokhoz köthetsz kódot.
Composable
Újrahasznosítható függvény, amely Vue-s reaktivitást (ref, watch, horgok) használ. A neve use-zal kezdődik.