Uvod
Koristeći Vue.js direktivu “v-for” dinamički generišemo HTML tzv. izlistavanje (mapiranje) podataka.
<div v-for="item in items">
Iako možda na prvi pogled izgleda logično da se direktiva stavi na parent element (“ul” ili “ol”), to ovde nije slučaj, kod Vue.js se direktiva “v-for” ugradjuje na HTML elemenat koji treba da se “izlistava”, tj. HTML elemenat na kojem je “zakačena” direktiva “v-for” će se koristiti kao template za renderovanje odgovarajućeg sadržaja.
Direktiva “v-for” koristi takozvanu “in-place patch” strategiju koja omogućava efikasno korišćenje resursa. Medjutim ovakav pristup u nekim slučajevima može da napravi problem u prikazivanju izlistanih elemenata, nakon njihovog sortiranja ili izmeni njihovog redosleda (npr. ako koristimo metodu koja meša redosled). Za ovaj problem postoji rešenje dodavanjem jedinstvenog “key” atributa svakom elementu, koji se “veže” (eng. “bind”) za taj element. U suštini dodavanje ovog dodatnog atributa je znak za Vue.js, da prati identitet svakog elementa i na taj način ispravno izvrši redefinisanje pozicije elementa. Za ključ treba izabrati neki jedinstveni podatak
v-bind:key="nekiJedinstveniParametar"
Preporuka je da se ovaj atribut obezbedi kad god je to moguće. Procitajte više o ovoj problematici na oficijelnoj strani ili na stranici “codingexplained.com” u clanku “Understanding-v-for-update-strategy”
Primer
1 2 3 |
<div v-for="item in items" v-bind:key="item.id" > <!-- content --> </div> |
Mapiranje nizova
Mapiranje običnog niza
Generalna sintaksa izgleda ovako:
1 2 3 |
v-for="(element) in array" // ili jednostavno: v-for="element in array" |
Ako je potreban i index, onda je sintaksa:
1 |
v-for="(element, index) in array" |
Primer
See the Pen Mapiranje obicnog niza by Web programiranje (@chos) on CodePen.
Kao što se vidi i u prethodnom primeru, u okviru “v-for” bloka takodje imamo pun pristup svim drugim data svojstvima (“grad”).
Mapiranje niza brojeva
Sličnom sintaksom može da se mapira i običan broj
Primer
1 2 3 4 5 |
<div id="app"> <ul> <li v-for="n in 10">{{n}}</li> // 1,2,3,4,5,6,7,8,9,10 </ul> </div> |
ili
1 2 3 4 5 6 |
<div id="app"> <ul> <li v-for="n in 10">{{11-n}}</li> // 10,9,8,7,6,5,4,3,2,1 </ul> <p>Launch missile!</p> </div> |
Mapiranje niza objekata sa istim svojstvima
Sve što je pomenuto za izlistavanje “običnog” niza, takodje važi i za izlistavanje niza koji sadrži objekte:
See the Pen Izlistavanje niza objekata by Web programiranje (@chos) on CodePen.
Mapiranje niza nejednakih objekta
Prethodi slučaj data objekta liči na listu objekata iz MySql baze, gde svi objekti imaju isti broj definisanih svojstava, ali šta ako koristimo MongDb bazu gde tako ne mora da bude? U tom slučaju da bi izlisatli sva svojstva (u nekom objektu može biti više ili manje svojstava) potrebno je da v-for stavimo i na “ul” tag, pogledajte primer:
See the Pen
Untitled by Web programiranje (@chos)
on CodePen.
Mapiranje mutiranog ili filtriranog niza
Direktiva “v-for” podržava menjanje niza koji se mapira sa metodama: push(), pop(), shift(), unshift(), splice(), sort() i reverse(). Medjutim Vue.js ne podržava direktno dodavanje članova na sledeći način:
1 |
data.voce[4] = {cena: 10, naziv: 'ananas'} |
Rešenje za direktno dodavanje elemenata u okviru Vue.js-a je korišćenje metode Vue.set()
1 |
Vue.set(data.voce, 4, {cena: 10, naziv: 'ananas'}); |
Takodje Vue.js ne podržava modifikaciju dužine niza na sledeći način:
1 |
data.voce.length = 2 |
Kondiciono mapiranje sa v-if
NAPOMENA:
Ukoliko se direktiva “v-for” koristi zajedno sa “v-if” na istom elementu, direktiva “v-for” ima viši prioritet od “v-if.“
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<ul id="app"> <li v-for="proizvod in voce" v-if="proizvod.cena>10"> {{ proizvod.ime }} - {{ proizvod.cena }}din </li> </ul> <script> new Vue({ el:"#app", data: { voce: [ {ime: 'jabuka', cena: '7'}, {ime: 'pomorandza', cena: '12'}, {ime: 'banana', cena: '20'} ] } }) </script> |
Prethodni kod će izlistati sve filtrirane članove niza čija je cena veća od 10:
- pomorandza – 12din
- banana – 20din
Filtriranje sa “computed” svojstvom
Umesto vezivanja za neku vrednost iz “data” objekta možemo za filtriranje niza da koristimo “computed” svojstvo.
Primer
See the Pen Filtriranje sa izlistavanjem – computed properties by Web programiranje (@chos) on CodePen.
NAPOMENA:
U prethodnom primeru obratite pažnju na izraz
let vockaVanClosure = this.vocka; koji nam omogućavama korišćenje vrednosti “vocka” u sklopu closure funkcije. Korišćenje “this.vocka” u okviru callback funkcije (closure) ne bi vraćalo očekivanu vrednost “data” svojstva “vocka”, već “undefined”. Više o tome kako se ponaša ključna reči “this” u okviru Vue.js, možete pročitati u članku “Pristup svojstvima Vue.js instance”
U ovome primeru computed svojstvo vraća niz, pa je jednostavno iskoristiti filtrirajPoCeni.length za izlistavanje koliko vrsta zadovoljava uslov. Takodje i u ovome primeru možemo dodati atribut na svakom elementu “v-bind:key=”proizvod.ime” i tako sprečiti moguće probleme pri sortiranju.
1 |
<li v-for="proizvod in filtrirajPoCeni" :key="proizvod.ime"> |
Filtriranje sa metodom
Koristeći metodu se dobija isti rezultat kao u prethodnom primeru za “computed” svojstvo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<ul> <li v-for="proizvod in filtrirajPoCeni(voce)"> {{ proizvod.ime }} - {{ proizvod.cena }}din </li> </ul> <script> new Vue({ el:"#app", data: { voce: [ {ime: 'jabuka', cena: '7'}, {ime: 'pomorandza', cena: '12'}, {ime: 'banana', cena: '20'} ] }, methods:{ filtrirajPoCeni: function(niz) { return niz.filter(function(elementNiza) { return elementNiza.cena > 10; }) } } }) </script> |
Da sprečili probleme koji nastaju pri sortiranju, tj. da bi pratili identite svakog elementa potrebno je dodati mu neki jedinstveni ključ. Ovo možemo da izvedemo vezivanjem jedinstvenog “key” atributa za svaki element sa “v-bind:key=”proizvod.ime”.
1 |
<li v-for="proizvod in filtrirajPoCeni(voce)" :key="proizvod.ime"> |
Primer
See the Pen filtriranje metoda by Web programiranje (@chos) on CodePen.
Mapiranje svojstava objekta
Generalna sintaksa izgleda ovako:
1 |
v-for="(value, key) in objekat" |
ili ako je potreban i index sintaksa za sve zajedno sa indeksom je:
1 |
v-for="(value, key, index) in objekat" |
Pri iteraciji kroz svojstva objekta, “indeks” je u rasponu od 0 do “n-1”, pri čemu je n redni broj svojstva objekta. Redosled kojim se nabrajaju svojstva nije fiksan, u praksi je redosled najčešće isti kao redosled umetanja svojstava, ali ni to nije zagarantovano.
Primer
Primer iteracije kroz objekat gde se koriste sva tri atributa: value, key, index
See the Pen Izlistavanje svojstva objekta by Web programiranje (@chos) on CodePen.
Primer
U ovome primeru je prikazano rednerovanje sa tzv. “duplom petljom”
See the Pen Dupla petlja by Web programiranje (@chos) on CodePen.
Mapiranje grupe elemenata
Direktiva “v-for” se može primeniti na samo jedan HTML element, a ako je porebno da se mapira više HTML elemenata, potrebno je da ih “obavijemo” sa nekim wrapper elementom na koji ćemo da “nakačimo” našu direktivu. Taj elemenat može da bude <div> tag ali je preporučeno da bude <template> tag jer ne ostavlja tragove u DOM-u.
See the Pen GyaVLE by Web programiranje (@chos) on CodePen.
Mapiranje komponenti
Za izlistavanje komponenti koristimo sintaksu “for…in”. Zbog već poznatog problema sa sortiranjem, potrebno je svaku komponentu jedinstveno obeležiti sa jedinstvenim atributom “key”
v-bind:key="nekiJedinstveniParametar".
Međutim komponente imaju samostalne domene, pa se podaci neće automatski ubaciti u komponentu. Stoga da bi prosledili podatke u komponentu moramo da ih “povežemo” za svaku komponentu
v-bind:item="item" i
v-bind:index="index"
1 2 3 4 5 6 |
<my-component v-for="(item, index) in items" v-bind:key="item.id"> v-bind:item="item" v-bind:index="index" </my-component> |