Vue.js: Szintaxis, data, methods, computed, mounted, komponensek, props. Single File Components.

Az első vue.js alkalmazásunk


A Vue.js az alkotóik szerint egy nélkülözhetetlen eszköz a modern webfelületek hatékony fejlesztésében. A Vue.js keretrendszert akkor ajánlott használni , ha egy applikációt emberközelibbé szeretnénk tenni, a DOM elemeit hatékonyabban irányíthassuk, gyorsan reagálhassunk a felhasználó igényeire és mobilalkalmazás-szerű benyomást kelthessünk az asztali alkalmazásunkon. Kezdésnek látogassunk el a Vue.js dokumentációjának kezdő honlapjára [1]. Számtalan lehetőség közül választhatunk miképp telepítsük fel a Vue.js keretrendszert. Amennyiben gyorsan szeretnénk prototípust készíteni, elegendő importálni a megfelelő scriptet online forrásból. Viszont ha komplex alkalmazást próbálnánk meg összerakni (pl. Webpack segítségével) és nem szeretnénk, hogy a használt könyvtárak verziószáma ne változzon, akkor lokális telepítés ajánlott. Az első lépésként példányosítsunk a Vue konstruktor függvény meghívásával new Vue(). A konstruktor függvény argumentuma vár egy objektumot, amiben konfigurálhatjuk, hogy miképp szeretnénk felhasználni. Az el tulajdonság segítségével megadhatjuk, hogy a DOM mely elemét szeretnénk vezérelni. A színfalak mögött ez az elem lerendelődik a DOM-ba és betöltődik, mint nézet. Legyen ez az elem egy <div id="app"></div> és rá úgy tudunk hivatkozni a Vue példányban, hogy el: #app. Az el tulajdonság segítségével megadhatjuk, hogy milyen adatokkal szeretnénk felhasználni az adott Vue példányhoz. Adjunk át neki az alábbi objektumot: cim: "Ez az első Vue,js alkalmazásom". Ezzel azt értük el, hogy a cim tulajdonságnak értékül adtuk az alábbi sztringet: "Ez az első Vue,js alkalmazásom". Ahhoz, hogy ezt meg is jeleníthessük a nézetben, a két <div> között, kettős kapcsos zárójel közé szúrjuk be a cim változót. Ezzel a szintaxissal bármilyen előre definiált változóra lehet hivatkozni, hogy a nézetben megjeleníthessük a pillanatnyi értékét.

<!--index.html-->
<!DOCTYPE html>
<html lang="hu">
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width,initial-scale=1.0">
		<title>Példa</title>
	</head>
	<body>
		<div id="app">
			<p>{{cim}}</p>
		</div>
	</body>
	<script src="https://cdn.jsdelivr.net/npm/vue"></script>
	<script>
		new Vue({
			el: '#app',
				data: {
				cim: 'Ez az első Vue.js alkalmazásom!'
					  }
				});
	</script>
<html>


A DOM és a virtuális DOM


A Vue.js egy HTML-alapú sablon (template) szintaxist használ, amiben lehetőségünk adódik, hogy összekössük a lerenderelt DOM-t a lepéldányosított Vue-val kapcsolatos adatokat. A motorháztető alatt a Vue lefordítja a sablont virtuális DOM renderelő függvényekké [7].

Vue.js reagáló rendszer

Számos JavaScript keretrendszer, beleértve a Vue.js-t is az úgynevezett Virtuális DOM-t használja. Elméletileg a DOM-ra gondolhatunk úgy, ami reprezentálja a HTML dokumentum felépítését. Gyakorlatilag a DOM egy olyan adatstruktúra ami akkor jön létre, amint a HTML dokumentumot a böngésző lefordítja. Amikor JavaScript segítségével változtatni kívánunk a megjelenített oldal állapotán, a böngésző elkezdi megkeresni a DOM-on belül a megfelelő csomópontokat amik érintettek lehetnek, végül azokat megváltoztatja. Egy modern alkalmazásban több ezer ilyen csomópont található a DOM-ban, amik frissítése rengeteg erőforrást emészt fel. A kisebb jellegű de gyakoribb frissítések elkerülhetetlenül lelassítják az oldal betöltését. A Virtuális DOM egyfajta egyszerűsített és leválasztott (lokális) absztraktciója a HTML DOM-nak, ami a memóriában helyezkedik el. A böngészőkön az elemek megjelenítése régebben úgy működött, hogy minden egyes változás bekövetkezte esetén (legyen az akármilyen kicsi jelentőségű) is lerenderelte a teljes DOM-t ahelyett, hogy csak a szükséges elemei frissítse. Szóval akárhányszor változás következik be mondjuk azzal ,hogy új elemet szeretnénk megjeleníteni a DOM-ban, egy virtuális DOM létrejön, ami első ízben nem végez semmi nemű változtatást a DOM-ban, csupán a különbséget vizsgáljuk az előző és jelenlegi virtuális DOM között. Ezt követően a példánál maradva az új elem be fog töltődni a DOM-ba anélkül, hogy az egészet újra renderelnénk. Virtuális DOM-t nem csak az erőforrás csökkentés miatt érdemes használni, hanem több funkcionalitást is kínál.

dinamikus DOM frissítés

Az MVVM tervezési minta


Minél jobban belemerülünk a Vue.js rejtelmeibe az derül ki, hogy valójában nem teljes értékű keretrendszerként funkcionál, hanem leginkább a nézet rétegre fókuszál. A Vue.js szívét képezi egy úgynevezett reaktív adat-összekötő rendszer, ami a saját speciális szintaxisát alkalmazva a megszokott HTML sablonunkban összeköthetjük a DOM-t az adatainkkal [46. oldal 14]. Az egyik leggyakrabban előforduló formája az adatunk és a DOM elemek összekötésének szintaktikailag a következőképpen néz ki: <p></p>, ahol az cim -hoz van valamilyen érték társítva. A kettős kapcsos zárójelek közé akár írhatunk komplett JavaScript kifejezéseket is, ezek is kiértékelődnek: <p>undefined Szöveg</p>. Amint a kapcsolat létrejött, a DOM és az adataink szinkronizálódnak. Minden egyes alkalommal amelyik adatunk változik, a DOM azon eleme is megváltozik, melyre hivatkozunk. Ennek a megközelítésnek az az előnye, hogy kizárólag az adatokra fókuszálhatunk, nem kell még külön szórakozni a DOM frissítésével. Ezáltal a kódunk könyebben olvasható és kezelhető lesz. Önmagában a Vue.js keretrendszer használatával automatikusan az úgynevezett model-nézet-modellnézet ( Model-View-ViewModel (MVVM)) tervezési minta szerint fejlesztünk alkalmazást. Amikor lepéldányosítjuk a konstruktor függvény meghívásával (new Vue()). , melynek argumentuma vár egy objektumot, amiben konfigurálhatjuk, hogy miképp szeretnénk az adatainkat összekötni a nézet réteggel. Az adattaink összegége (és az üzleti logika) képezi a modell (Model) réteget, a DOM elem - amivel összekötjük a Vue példányt - képezi a nézet réteget (View). Eközben a Vue példányunk képezi a nézetmodell réteget (ViewModel), ami létrehozza és fenntartja a kapcsolatot a modell és a nézet réteg között. Ezáltal a nézet réteg teljes egészében adatvezéreltté válik. Vegyük példának az első Vue.js alkalmazásunkat:

Az alkalmazásunk egyszerűsített MVVM diagrammja

Megjegyzésként megemlítenénk, hogy a fenti képen a jól láthatóság kedvéért a data tulajdonsághoz nem közvetlenül rendeltük hozzá az adatunkat, hanem egy korábban deklarált adat elnevezésű változóhoz rendeltük hozzá és ezt hivatkoztuk meg a data tulajdonsághoz.

Az adat és a metódus tulajdonságok


A data egy olyan objektum kulcs a Vue példányban, melynek értéke szintén egy objektum. A Vue példányban itt deklarálhatjuk a kívánt adatokat, azaz a data tulajdonság képezi a modell réteget. Minden egyes adat this kontextusa a neki megfelelő Vue példányhoz fog kötődni. Tegyük fel azt az esetet, amikor a Vue példányt egy változóhoz rendeljük (valtozo névvel) és ellátjuk a megfelelő adatokkal (adat). Ekkor az alábbi szintaxis szerint érhetjük el az adatainkat kívülről: valtozo$data._adat. A method egy olyan objektum kulcs a Vue példányban, melynek értéke szintén egy objektum. A Vue példányban itt deklarálhatjuk a kívánt metódusainkat, melyek segítségével szinkron és aszinkron műveleteket műveleteket hajthatunk végre. Minden egyes metódus this kontextusa a neki megfelelő Vue példányhoz fog kötődni. Tegyük fel azt az esetet, amikor a Vue példányt egy változóhoz rendeljük (valtozo névvel) és ellátjuk a megfelelő metódusokkal. (metodus). Ekkor az alábbi szintaxis szerint érhetjük el a metódusainkat kívülről: valtozo.metodus().

Direktívák


A direktíva egy olyan speciális attribútum, melyhez köthetünk JavaScript kifejezést. A direktívák egítségével reaktív viselkedést kölcsönözhetünk a megcélzott DOM elemeknek, amikor a kifejezés megváltozik. Számos beépített direktívát érhetünk el és mindegyiknek megvan a saját speciális funkcionalitása [2]. Ezen felül mi magunk is definiálhatunk direktívákat. Szintaxisa szerint: v-direktiva_attributum:direktiva_argumentum.direktiva_modosito="javascript_kifejezes". Itt a v- prefixummal jelezzük a fordítónak, hogy direktívát próbálunk deklarálni. Néhány direktívához tartozhatnak argumentumok, melyet kettősponttal választunk el a direktíva nevétől. Az argumentumokhoz tartozhatnak módosítók, melyeket ponttal választunk el az argumentumtól. Végezetül ="" mentén hivatkozhatjuk megn a kívánt JavaScript kifejezést.

Esemény direktívák


A következő lépésként nézzük meg, hogyan figyelhetünk egy esemény bekövetkeztére. Deklaráljunk egy gombot valamilyen névvel. Az események figyelésére szakosodott direktíva a v-on. Többféle eseményt különböztetünk meg, a kattintás esetén v-on:click. Végül a ="" mentén definiálhatjuk a kódot, amit végre szeretnénk hajtani. Legyen a példa az, hogy gombnyomásra változtassuk meg a kezdeti szöveget valamilyen más szövegre egy metódus meghívásával. A következő lépésként hozzunk létre egy methods tulajdonságot a lepéldányosított Vue-ban, melynek értéke legyen egy objektum. Itt definiálhatjuk a metódusokat. A Vue példányon belül definiált összes tulajdonságot és metódust a this kulcsszóval tudjuk meghivatkozni (kontextus).

<!--index.html-->
<!DOCTYPE html>
<html lang="hu">
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width,initial-scale=1.0">
		<title>Példa</title>
		<style>
		</style>
	</head>
	<body>
		<div id="app">
			<button v-on:click="cimvaltoztat">Szöveg megváltoztatása</button>
			<p>{{cim}}</p>
		</div>
	</body>
	<script src="https://cdn.jsdelivr.net/npm/vue"></script>
	<script>
		new Vue({
			el: '#app',
			data: {
				cim: 'Ez az első Vue.js alkalmazásom!'
			},
			methods: {
				cimvaltoztat(){
					this.cim='Ez egy masik szöveg'
				}
			}
		});
	</script>
<html>
Esemény direktívák


A következő lépésként tároljuk el azt, amit a felhasználó begépel. A JavaScriptben amint bekövetkezik egy esemény egy alapértelmezett esemény objektumot adunk át az esemény figyelő számára. Ez az objektum tartalmazza az események forrását legyen az gomb, bemeneti mező, stb. amire később hivatkozhatunk. Példaként egy bemeneti eseményt azon bemeneti mezővel lehet összekötni, ahova a felhasználó éppen gépelt karaktereket. A cél az, hogy hivatkozni tudjunk erre a bemeneti mezőre, hogy hozzá tudjunk férni a begépelt értékhez. Vuejs-ben az alábbi kód deklarálásával férhetünk hozzá ezen értékekhez az eseményt kiváltó elemnél: $event.target.value. A direktívákat nemcsak események figyelésére, hanem egy elem dinamikus módon történő "összekapcsolását" is megoldhatjuk vele. Az előbb tárgyaltaktól eltérően ezúttal nem értékeket szeretnénk lekérni egy bemeneti mezőből (az előző példánál maradva), hanem értékeket közvetíteni szeretnénk a bemeneti mező felé. Így a kommunikáció már oda-vissza történhet a felhasználó és az applikáció között. Az erre a célra használatos direktíva a v-bind:attributum_neve, ahol az attributum_neve a kérdéses attributum, amivel össze akarom kötni az adott elemet dinamikusan. Végül a "" mentén definiálhatjuk azt a kifejezést, amit végre szeretnénk hajtani. Az egyik leggyakrabban összekötött attribútumok, melyeket összekötnek az elemekkel, a HTML attribútumok (például class és style). Egy példa keretén belül meg szeretnénk változtatni egy elem pixelben megadott méretét dinamikusan aszerint, hogy egy szám típusú bemenetbe milyen számot gépeltünk be. Szintaktikája szerint többféleképpen implementálhatjuk a megoldást, a könnyedség érdeképen maradjunk az úgynevezett objektum megközelítésnél: v-bind:style="{ fontSize: valtozo_neve + 'px' }".

<!--index.html-->
<!DOCTYPE html>
<html lang="hu">
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width,initial-scale=1.0">
		<title>Példa</title>
		<style>
		</style>
	</head>
	<body>
		<div id="app">
			<input type="szam" v-on:input="valtozo=$event.target.value">
			<p v-bind:style="{ fontSize: valtozo + 'px' }">Begépelt szám: {{valtozo}}</p>
		</div>
	</body>
	<script src="https://cdn.jsdelivr.net/npm/vue"></script>
	<script>
		new Vue({
			el: '#app',
			data: {
				valtozo: ''
			}
		});
	</script>
<html>
Esemény direktívák (2)


Feltételes direktívák


Az eddig tanultak alapján képesek vagyunk megjeleníteni adatokat a felhasználók számára. Az átláthatóség szempontjából nem tenne jót egy átlag felhasználónak (biztonsági okokból pedig az alkalmazás szolgáltatójának), ha az összes adatot a nyakába zúdítanánk egyetlen nézetre. Feltételekhez kötve definiálhatunk különböző nézeteket, ahol minden egyes nézet egy-egy külön fájlnak feleltetünk meg, melyeket szolgáltathatunk a felhasználók felé a szerverünk segítségével. Ez a megoldás rendkívül körülményessé vállhat (nem beszélve az adatforgalomról), ha például olyan alkalmazásról beszélünk, ami sok tucatnyi regisztrált felhasználót kiszolgáló alkalmazásról van szó. Egy másik megközelítés szerint ugyanazt az oldalt/fájlt szolgáltatva több különböző nézetet is meg tudunk jeleníteni attól függően, hogy az általunk definiált feltételek teljesültek-e, vagy sem. Néhány egyszerű példa keretén belül megmutatjuk, hogy a felhasználó térfelén a Vue.js segítségével a HTML elemek megjeleníthetőségét miképp köthetjük feltételekhez, kialakítva ezzel a különböző nézeteket. Az egyik példánk legyen az, hogy egy <p></p> és tartalmának megjelenítését kössük feltételhez. A direktívák erre a problémára is megoldást nyújtanak, méghozzá a v-if és v-show. Ezen direktívák egy feltételt definiáló kifejezést várnak a ="" mentén, melyeknek valamilyen logikai értékkel kell visszatérniük. Amennyiben a feltétel teljesül, az adott HTML elem megjelenítődik az oldalunkon, egyébként nem. A két direktíva között annyi különbség van, amíg a v-if esetén az adott elem valóban megjelenik/eltűnik a DOM-ban, addig a v-show esetén az inline stílust megváltoztatva (style="display: none;") imitáljuk az elem eltűnését/előbukkanását. A v-if ághoz tartozhat egy v-else alapértelmezett ág is. Az egyetlen kitötés rá, hogy ugyanolyan típusú elemre lehet else ágat implementálni, amilyenre az if ágat. A lenti példában létrehoztunk egy Vue példányt feltetel változóval true értékkel inicializálva, egy valtoztat metódussal, melynek meghívása esetén (gombnyomásra reagálva) a feltetel változó értékét megváltoztatja. Van három paragrafus, az egyikre if ágat rakunk, a másikra else ágat, a harmadikra pedig a v-show direktívát.

<!--index.html-->
<!DOCTYPE html>
<html lang="hu">
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width,initial-scale=1.0">
		<title>Példa</title>
		<style>
		</style>
	</head>
	<body>
		<div id="app">
			<button v-on:click="valtoztat">Láthatóság megváltoztatása</button>
			<p v-if="feltetel">Látható vagyok v-if segítségével</p>
			<p v-else>Látható vagyok v-else segítségével</p>
			<p v-show="feltetel">Látható vagyok v-show segítségével</p>
		</div>
	</body>
	<script src="https://cdn.jsdelivr.net/npm/vue"></script>
	<script>
		new Vue({
			el: '#app',
			data: {
				feltetel: true
			},
			methods: {
				valtoztat(){
					this.feltetel=!this.feltetel
				}
			}
		});
	</script>
<html>
Feltételes direktívák


A listázó direktíva


Tegyük fel, hogy van egy listányi adatunk melyet be szeretnénk tölteni a sablonba/DOM-ba, hogy a felhasználók tudomást szerezhessenek róla. Ebben az esetben a v-for direktíva nyújthat segítséget. Szintaxisa szerint egy olyan kifejezést vár, melyben az egyik része egy tömbre/objektumra mutató változó amin végi kell iterálni, a másik fele pedig a tömb/objektum aktuális elemét reprezentálja a ="" mentén: v-for="elem in tomb". A v-for-nak van egy opcionális argumentuma, ami az indexelést könnyíti meg. Amennyiben a tömb/objektum rendelkezik egyedi elemekkel, a Vue.js lehetőséget nyújt ezen elemek hatékonyabb nyomon követésére a v-bind:key="elem.id" direktívával. Tegyük fel, hogy egy tömbnyi számot szeretnénk megjelenítani, ezt követően pedig szeretnénk növekvő sorba rakni a tömb elemeit. Alapártelmezetten a Vue.js a beillesztés-alapú frissítés technikáját használja a nézet frissítéséhez ami annyit takar, hogy először sorba rendeződnek a számok, aztán az újrarendezett tömb teljes tartalmát (mint HTML elem) újra renderelődik és betöltődik a DOM-ba. A v-bind:key direktívát használva a tömb elemei számon vannak tartvaés kizárólag az érintett tömbelemek fognak újrarenderelődni, amivel számításigényes feladatok esetén rengeteg erőforrást takaríthatunk meg. A feladatunk legyen az, tartsunk nyilván egy listányi nevet és írassunk ki a felhasználó számára. Az adatstruktúra legyen egy tömb, melynek minden eleme egy-egy objektum, id és nev tulajdonsággal. Legyen az id tulajdonság az egyedi kulcsunk és kössük össze a v-bind:key direktívával.

<!--index.html-->
<!DOCTYPE html>
<html lang="hu">
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width,initial-scale=1.0">
		<title>Példa</title>
		<style>
		</style>
	</head>
	<body>
		<div id="app">
			<ul>
				<li 
					v-for="(elem, index)       in tomb"
					v-bind:key="elem.id"
					>index: {{index}}            id: {{elem.id}}
					nev: {{elem.nev}}
				</li>
			</ul>
		</div>
	</body>
	<script src="https://cdn.jsdelivr.net/npm/vue"></script>
	<script>
		new Vue({
			el: '#app',
			data: {
				tomb: [
					{id: 1, nev: 'Gábor'},
					{id: 2, nev: 'Zsolt'},
					{id: 3, nev: 'Nóra'},
				]
			},
			methods: {

			}
		});
	</script>
<html>
A listázó direktíva


A számolt és a figyelő tulajdonság


A Vue.js egyik rendkívül hasznos funkcióját számolt tulajdonságnak hívnak (computed property). Általánosságban akkor érdemes használni, amikor össze akarunk kötni egymástól korábban független tulajdonságot és valamilyen értékkel vissza kell térni. Egy számolt tulajdonság csak akkor értékelődik újra, amennyiben az egyik függő tulajdonsághoz rendelt érték meg nem változik [3]. A koncepció tovább csiszolásával és általánosításával megszületett a figyelő tulajdonság (watch property). Mindezen fejlesztések arra szolgálnak, hogy az adatokban történt változásokat könnyebben nyomon követhessük és kezelhessük le. A lenti példában létrehoztunk egy Vue példányt egy szam változóval, novel és figyelmeztet metódusokkal, szamlalo számolt tulajdonsággal és a szam változót szemmel követő figyelőt. Az oldalon gombnyomásra 1-egyel megnövekszik a szam értéke. Amint változik a szam változónak az értéke egyrészt a szamlalo reagál és más értékkel tér vissza, másrészt figyelőt deklarálva ugyanerre a változóra végrehatdódik a figyelmeztet metódus.

<!--index.html-->
<!DOCTYPE html>
<html lang="hu">
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width,initial-scale=1.0">
		<title>Példa</title>
		<style>
		</style>
	</head>
	<body>
		<div id="app">
			<button v-on:click="novel">Érték növelése</button>
			<p>A gomblenyomás száma: {{szam}}</p>
			<p>Számolt érték: {{masikszamlalo}}</p>
		</div>
	</body>
	<script src="https://cdn.jsdelivr.net/npm/vue"></script>
	<script>
		new Vue({
			el: '#app',
			data: {
				szam: 0
			},
			methods: {
				novel(){
					this.szam++;
				},
				figyelmeztet(){
					alert(`A szám változó értéke az alábbira változott: ${this.szam}`);
				}
			},
			computed: {
				masikszamlalo(){
					return this.szamr*this.szam
				}
			},
			watch: {
				szam(val){
					if(val){
						this.figyelmeztet()
					}
				}
			}
		});
	</script>
<html>
A számolt és figyelő tulajdonság


Vue.js komponensek


A komponens a Vue.js keretrendszer egyik kulcsfontosságú koncepciója ami megadja azt a lehetőséget, hogy a kódunkat egyrészt funkcionalitás szerint csoportosíthatjuk, másrészt újrafelhasználhatjuk (rengeteg sornyi kódot megspórolva) [4]. Nem szükséges magunknak újraírni teljes komponenseket ha találunk az interneten való böngészés során funkcionalitásban hasonló komponenseket, elegendő azokat módosítani. Úgy képzelhetjül el őket, mint a LEGO kockák: egymással összeilleszthetjük őket és bármit építhetünk belőle. Az alkalmazásban egy-egy nézet eltérő helyet foglal el a képernyőn. Amikor egy alkalmazás sok, de kis helyet elfoglaló nézetet tartalmaz, szokás egymásba ágyazni őket. A Vue.js keretrendszerben egy úgy valósítható meg, hogy a komponenseket egyszerűen egymásban meghivatkozzuk. Kétféle megközelítés ismert: az összes komponens deklarálása a main.js fájlban, továbbá minden egyes komponens implementálása külön fájlokként. Mind a két megközelítést tárgyalni fogjuk, egyenlőre fókuszáljunk az elsőre. Tegyük fel, hogy egy-egy funkcionalitást egy-egy komponens segítségével szeretnénk megvalósítani. A funkciók eléréséhez az egyes komponenst regisztrálni és végrehajtani kell a main.js fájlban. A komponenseket regisztrálhatjuk globálisan és lokálisan. Ebben az esetben tegyük globálisan elérhetővé a komponenseket a Vue.component(nev,beallitasok) metódus meghívásával. Globálisan regisztrált komponenst bármely másik komponensben meghívható, ugyanazon Vue példányán belül. Az első paraméter a komponens neve, amilyen név szerint szeretnénk regisztrálni. A második paraméter egy objektumot vár, amiben a komponenst definiáljuk. Minden egyes komponens tartalmaz egy <template></template> szekciót, amiben a nézetünk felépítését definiálhatjuk. Ebben az esetben használjuk a sztring literál deklarálási formát. A <template></template> egészen pontosan egyetlen gyökér elemet tartalmazhat. Ha több HTML elemből építettük fel a nézetet, akkor szúrjuk be őket egy <div></div>. A nézeten belül a következőképpen hívhatunk meg egy tetszőleges komponenst: <komponens_neve ></komponens_neve >, ahol komponens_neve a komponens regisztrált neve. A Vue példányunkhoz hasonlóan itt is értelmezve van a data tulajdonság. Azonban a data itt egy függvény, ami egy objektummal tér vissza. Ha a data tulajdonság egy objektumot tartalmazna, akkor minden egyes komponens ugyanazon az adatokon fog osztozni, tehát az újrafelhasználhatóság koncepcióját dobhatnánk a kukába, nem használhatjuk sablonként. Ehelyett visszatérünk egy objektummal a data függvény segítségével, így minden adat egyedi lesz, ahányszor hívjuk meg a kérdéses komponenst. Definíció szerint azt a komponenst, amibe ágyazunk egy másikat szülő komponensnek nevezzük, amit beleágyaztunk pedig gyerek komponensnek hívjuk.

A komponensek hiearchiája

Mi a helyzet akkor, amikor az egymásba ágyazott komponensek között adatokat szeretnénk cserélni. Minden egyes komponens természetétől adódóan a hatóköre nem nyúlik ki saját magán túlra. Az akadály áthidalására találták ki a props tulajdonságot. Ez a tulajdonság egy objektumot vár, melynek elemei olyan tulajdonságok, melyek csatornaként funkcionláva megoszthatunk adatokat egymással szomszédos kapcsolatban álló komponens között. Minden változó vár egy objektumot, amiben többek között konfigurálhatjuk az átadott értékek típusát, az alapértelmezett értéket, és így tovább. A szülő komponensből kiindulva adatokat dinamikusan a gyerek komponens számára úgy tudunk elküldeni, hogy a \verb|v-bind| direktíva segítségével összekötjük a props-ban definiált változót (mint attribútum) a szülőben definiált változóval, ami valamilyen értékre mutat: v-bind:gyerek_prop="szulo_valtozo". A létrehozott kommunikációs csatorna akkor válik teljessé, ha a másik irányba is történet adatcsere, azaz gyerek -> szülő. Mi a helyzet akkor, amikor egy szülő objektumot szeretnénk értesíteni egy a gyerek komponensben bekövetkezett eseményről? Ezt úgy tudjuk megvalósítani, hogy egy esemény objektumot küldünk el. Egy ilyen objektumot magunk nevezhetünk el és opcionálisan adatot is beilleszthetünk be objektum formájában. Vegyük az alábbi esetet: Egy gyerek komponens tartalmaz egy bemeneti mezőt és egy metódust, amik össze vannak kötve. Akárhányszor begépelünk valamit a bemeneti mezőbe, mindig meghívjuk az összekötött metódust és átadjuk neki az esemény objektumot. A metódus deklarációjánál az argumentumban értelmezve van egy kifejezés, ami az esemény objektumot takarja, az elnevezés tetszőleges. Ennek az objektumnak értelmezve van a target attribútum, ami az esemény forrását azonosítja be. Ahhoz, hogy effektíve megkaphassuk a forrástól származó adatokat, a value tulajdonságot hívjuk meg. Ezt követően a this.$emit(’esemeny_neve’, event.target.value) segítségével megvalósíthatjuk az adatok továbbküldését, ahol esemeny_neve az esemény neve, amire a túloldalt számíthatunk. Ahhoz, hogy a túloldalt (a szülő komponens) foghassa a vételt, a gyerek komponenst reprezentáló elemnél használhatjuk az események figyelésére kitalált v-on direktívát és az argumentumába adjuk át annak az események a nevét, amelyre kíváncsiak vagyunk. A =”” mentén pedig definiálhatunk egy kifejezést, aminek átadhatjuk a kapott esemény objektumot. Ebben az esetben legyen ez egy metódus, ami a szülő komponensben van deklarálva. A gyerek komponenshez hasonlóan lekérjük a kívánt adatokat, amit aztán arra használhatunk fel, amire akarjuk: v-on:esemeny_neve=”szulo_metodus”. Ezzel sikeresen megvalósítotttunk két, egymásba ágyazott komponens közti kétirányú kommunikációt.

A létrehozott kommunikációs csatorna akkor válik teljessé, ha a másik irányba is történet adatcsere, azaz gyerek -> szülő. Mi a helyzet akkor, amikor egy szülő objektumot szeretnénk értesíteni egy a gyerek komponensben bekövetkezett eseményről? Ezt úgy tudjuk megvalósítani, hogy egy esemény objektumot küldünk el. Egy ilyen objektumot magunk nevezhetünk el és opcionálisan adatot is beilleszthetünk be objektum formájában. Vegyük az alábbi példát. Egy gyerek komponens tartalmaz egy bemeneti mezőt és egy metódust, amik össze vannak kötve. Akárhányszor bepötyögünk valamit a bemeneti mezőbe, mindig meghívjuk az összekötött metódust és átadjuk neki az esemény objektumot. A metódus deklarációjánál az argumentumban értelmezve van egy kifejezés, ami az esemény objektumot takarja, az elnevezés tetszőleges. Ennek az objektumnak értelmezve van a target attribútum, ami az esemény forrását azonosítja be. Ahhoz, hogy effektíve megkaphassuk a forrástól származó adatokat, a value tulajdonságot hívjuk meg. Ezt követően a this.$emit(’esemeny_neve’, event.target.value) segítségével megvalósíthatjuk az adatok továbbküldését, ahol esemeny_neve az esemény neve, amire a túloldalt számíthatunk. Ahhoz, hogy a túloldalt (a szülő komponens) foghassa a vételt, a gyerek komponenst reprezentáló elemnél használhatjuk az események figyelésére kitalált v-on direktívát és az argumentumába adjuk át annak az események a nevét, amelyre kíváncsiak vagyunk. A =”” mentén pedig definiálhatunk egy kifejezést, aminek átadhatjuk a kapott esemény objektumot. Ebben az esetben legyen ez egy metódus, ami a szülő komponensben van deklarálva. A gyerek komponenshez hasonlóan lekérjük a kívánt adatokat, amit aztán arra használhatunk fel, amire akarjuk: v-on:esemeny_neve=”szulo_metodus”. Ezzel sikeresen megvalósítotttunk két, egymásba ágyazott komponens közti kétirányú kommunikációt.

Az eddigi ismereteink szerint a beviteli mezők és a bevitt értékeket tároló változók közti kommunikáció egyirányú, az előző példában a kétirányúságot két különböző kommunikációs forma ötvözéséből hoztuk össze. Sok esetben rendkívül hasznos lenne egy ilyen kommunikációs forma egyrészt a könnyű implementálás, másrészt az áttekinthetőség szempontjából. Az igények nem találtak süket fülekre, meg is alkották az erre szakosodott direktívát: v-model. Szintaxisa szerint a =”” mentén egy változót vár, amin keresztül történhet a kétirányú kommunikáció. Ez a megoldás ekvivalens azzal, amikor egy bemeneti mezőt összekötünk egy változóval v-bind:value és v-bind:input direktívákkal (<input v-bind:value="valtozo" v-on:input="valtozo = $event.target.value").

<!--index.html-->
<!DOCTYPE html>
<html lang="hu">
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width,initial-scale=1.0">
		<title>Példa</title>
		<style>
		</style>
	</head>
	<body>
        <div id="app">
            <p>Szülő komponens</p>A gyerek komponens felé:
        	<input type="text" 
                v-on:input="valtozofrissit"> 
                    &nbsp; {{valtozo}}
            <p>A gyerek komponenstől: {{harmadikvaltozo}}</p>
            Kétirányú adatátvitel bemeneti mező 1:
            <input type="text" v-model="ketiranyuadat">
            <br>
            <br>
            Kétirányú adatátvitel bemeneti mező  2:
            <input type="text" v-model="ketiranyuadat">
            <hr>
            <komponens_neve 
                v-bind:gyerektulajdonsag="valtozo" 
                v-on:childevent="harmadikvaltozofrissit">
            </komponens_neve>
        </div>
	</body>
	<script src="https://cdn.jsdelivr.net/npm/vue"></script>
	<script>
        Vue.component('komponens_neve',{
            props: {
                gyerektulajdonsag: {
                     required: true,
                    type: String,
                    default: ""
                }
            },
            template: `<div>
                <p>Gyerek komponens</p>
                    <p>A szülő komponenstől: {{gyerektulajdonsag}}
                    <p>
                    <p>A gyerek komponens felé: 
                       <input type="text" 
                       v-on:input="masikvaltozofrissit">
                        &nbsp;
                        {{masikvaltozo}}                 
                    </p>
               </div>`,
            data: function(){
                return {
                    masikvaltozo: ''
                }   
            },
            methods: {
                masikvaltozofrissit(event){
                    this.masikvaltozo=event.target.value
                    this.$emit('gyerekesemeny', event.target.value)
                 }
            }
        });

        new Vue({
            el: '#app',
	        data: {
		        valtozo: "",
                harmadikvaltozo: "",
                ketiranyuadat: ""
	        },
            methods: {
                valtozofrissit(event){
                    this.valtozo=event.target.value
                },
                harmadikvaltozofrissit(value){
                    this.harmadikvaltozo=value
                }
            }
        });
	</script>
<html>
Szülő-gyerek adatcsere
Szülő-gyerek adatcsere (2)


Irodalomjegyzék

[1]
Vue.js core team. Vue.js: The Progressive JavaScript Framework. https://vuejs.org, Legutóbb megtekintve: 2019. április 22.
[2]
Vue.js core team. API, Global Config, directive. https://vuex.vuejs.org/vuex.png, Legutóbb megtekintve: 2019. április 22.
[3]
Vue.js core team. API, Global Config, computed. https://vuejs.org/v2/api/#computed, Legutóbb megtekintve: 2019. április 22.
[4]
Vue.js core team. API, Global Config, components. https://vuejs.org/v2/api/#components, Legutóbb megtekintve: 2019. április 22.
[5]
Vue.js core team. Vue-CLI. https://cli.vuejs.org/guide/creating-a-project.html#vue-create, Legutóbb megtekintve: 2019. április 22.
[6]
Vue.js core team. Vue-router. https://router.vuejs.org/guide/#html, Legutóbb megtekintve: 2019. április 22.
[7]
Vue.js core team. Render Functions and JSX. https://vuejs.org/v2/guide/render-function.html, Legutóbb megtekintve: 2019. április 22.
[8]
w3schools core team. JavaScript RegExp Reference. https://www.w3schools.com/jsref/jsref_obj_regexp.asp, Legutóbb megtekintve: 2019. április 22.
[9]
Google Chrome DevTools core team. Chrome DevTools. https://developers.google.com/web/tools/chrome-devtools, Legutóbb megtekintve: 2019. április 22.
[10]
Node.js core team. Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. https://nodejs.org/en/, Legutóbb megtekintve: 2019. április 22.
[11]
NPMJS core team. NPMJS. https://www.npmjs.com, Legutóbb megtekintve: 2019. április 22.
[12]
ExpressJS core team. Express Fast, unopinionated, minimalist web framework for Node.js. https://expressjs.com, Legutóbb megtekintve: 2019. április 22.
[13]
EJS core team. EJS: Embedded JavaScript templating. https://ejs.co, Legutóbb megtekintve: 2019. április 22.
[14]
Olga Filipova. Learning Vue.js 2. Packt Publishing Ltd., Livery Place, 35 Livery Street, Birmingham, B3 2PB, UK, 3, 2016.
[15]
E.F. Codd. A relational Model of Data for Large Shared Data Banks. Communications of the ACM, 13 (6) 1970.
[16]
Papp Edit. Adatbáziskezelés. Booklands 2000 Könyvkiadó Kft., 5600 Békéscsaba, Dr. Becsey Oszkár u. 42., 1, 2004.
[17]
Nemzeti Szakképzési és Felnőttképzési hivatal. Szoftverfejlesztő tanfolyam. https://www.nive.hu, Legutóbb megtekintve: 2019. április 22.
[18]
JavaScript.info core team. JavaScript.info. https://javascript.info/promise-basics, Legutóbb megtekintve: 2019. április 22.
[19]
Craig Buckler. Sitepoint (JavaScript) - Understanding ES6 Modules. https://www.sitepoint.com/understanding-es6-modules/, Legutóbb megtekintve: 2019. április 22.