methods
Svojstva u okviru Methods su funkcije vezane za Vue instancu. “Metode” se koriste kada želite da se nešto izvrši nakon nekog događaja ili kada želite da se funkcija izvrši kada god se promeni stanje instance/komponente nakon čega se DOM re-renderuje. “Metode” se takodje izvršavaju pri svakom učitavanju instance (komponente).
When this data changes, the view will re-render. Method invocation will always run the function whenever a re-render happens.
Dokumentacija Vue.js
Ovakvo ponašanje metoda je omogućeno time što Vue.js ne vodi računa šta se nalazi u okviru metode pa će metoda, biti ponovo proračunata čak iako promena ne utiče na metodu.
Primer
U ovome primeru imamo dve metode (“obavestenje()” i “ispisiVrednostB()”) čije su funkcionalnost jednostavne i opisane samim nazivom metode. Medjutim funkcionalnost koja je važna u ovome primeru je ispisivanje poruke u konzoli svaki put kada se klikne bilo koje dugme.
Kao prva stvar na koju treba obratiti pažnju je činjenica da se odmah nakon učitavanja Vue instance u konzoli ispisuju poruke iz obe metode, što potvrdjuje činjenicu da se metode izvršavaju pri svakom učitavanju Vue instance (komponente).
Zatim treba pratiti konzolu nakon svakog klika na akciono dugme, jer se nakon svakog klika ispisuju po dve nove poruke, bez obzira koje dugme je kliknuto. Ovo ukazuje da se obe metode izvršavaju svaki put kada se re-renderuje DOM nakon promene nekog od data svojstava, pa čak i metoda na koju promena data svojstva ne utiče.
See the Pen Specifičnost metoda u Vue.js by Web programiranje (@chos) on CodePen.
Zaključak:
Stoga zbog svega pomenutog treba naglasiti da u slučaju čestog ažuriranja user interfejsa, može doći do problema sa preformansama aplikacije, jer se troše resursi pri ponovnom pokretanja svih metoda. Na primer, ako imamo aplikaciju koja prikazuje tajmer koji se ažurira posle svake sekund, sve funkcije u okviu “methods” objekta će biti pozivane za izvršenje posle svake sekunde, i ponovno izračunati bez obzira na to koja im je namena. U ovakvom slučaju je preporuka koristi computed properties.
computed
“Computed” svojstva su u produžena ruka data svojstva, ona takodje vraćaju vrednost kao i data svojstvo:
See the Pen
Computed je extenzija data svojstva by Web programiranje (@chos)
on CodePen.
Iz prethodnog primera se vidi da su “computed svojstva” veoma korisna za manipulisanje sa već postojećim podacima. Pošto kao i data uvek vraćaju vrednost onda ime takve funkcije postaje svojstvo te se u aplikaciji koristi isto kao što koristimo “data” svojstvo (ne moramo ga pozivamo kao metodu). U suštini, “computed” svojstva su varijable, čije vrednosti zavise od drugih faktora i neće se ponovno izračunavati ako se zavisnosti ne promene. Što implicira da će funkcija iskoristiti svoju već prethodno izračunatu (tzv.kaširanu) vrednost, dok god nema promene zavisnosti.
Computed svojstva nisu namenjene za memorisanje podataka, štaviše, ako “computed” svojstvo vraća objekat, to će uvek biti novi objekat, a ne modifikovana verzija prethodnog. “Computed” svojstva moraju da budu funkcije čije akcije moraju da budu sinhrone i ne bi trebalo da imaju sporedne efekte.
Kada koristiti Computed properties?
Funkcije unutar “computed” svojstva se koriste kad god imamo neke podatke sa kojima trebamo da manipulišemo, da se transformišu, filtriraju, a pre nego što ih iskoristimo u template. Koristite “computed” svojstva kada želite da mutirate svojstvo koje zavisi od promene drugog svojstva koja se menja. “Computed” svojstva treba koristiti kao zamenu za inline izraze u okviru template kada imamo složeniju logiku.
Neki od primera zadataka koji su dobri kandidati za korišćenje “computed” svojstava su:
- Ažuriranje velike količine informacija dok korisnik piše, kao što je filtriranje liste
- Prikupljanje informacija iz “Vuex store”
- Validacija forme
- Vizualizacije podataka koje se menjaju u zavisnosti od toga šta korisnik treba da vidi
Primer
U ovom primeru je prikazano korišćenje “computed” svojstva za veliki set operacija:
1 2 3 4 5 6 |
computed: { velikiProracun () { // ... neki veliki proračun koji nakon nekog vremena vraća rezultat return 2 } } |
Sada rezultat ovih “teških” proračuna možemo koristiti iznova i iznova u okviru drugih operacija bez bojazni da će se ponovo proračunavati ako nema potrebe (tj. ako se nisu promenile :
1 2 3 4 5 |
methods: { jednostavniProracun (input) { return input * this.velikiProracun } } |
Da li koristiti “computed” ili “methods” svojstvo?
Ovu dilemu ću pokušati da objasnim kroz primer u kome iako koristimo različita svojstva dobijamo istu krajnju funkcoionalnost.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<div id="example"> <p>Originalna poruka: "{{ message }}"</p> <p>Obrnuta poruka: "{{ reversedMessage() }}"</p> </div> <script> var vm = new Vue({ el: '#example', data: { message: 'Hello' }, methods: { reversedMessage: function () { return this.message.split('').reverse().join('') } } }) </script> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<div id="example"> <p>Originalna poruka: "{{ message }}"</p> <p>Obrnuta poruka: "{{ reversedMessage }}"</p> </div> <script> var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { reversedMessage: function () { return this.message.split('').reverse().join('') } } }) </script> |
Krajnji rezultat je jednak, ali to ne znači da razlika ne postoji. Funkcija unutar “methods” će se izvršiti svaki put kada se renderuje stranica tj. pri svakoj mogućoj promeni DOM-a (ne samo promena svojstva “messages”), dok pri korišćenju computed svojstva Vue pamti vrednost svojstva od koje computed svojstvo zavisi (messages) i proračunava computed svojstvo samo ako se “dependency” promeni, u svakom drugom slučaju vraća keširanu vrednost.
Zaključujemo:
ako logika naše aplikacije ima “teške” proračune, a ne zahteva ponovno proračunavanje svojstva pri svakom renederovanju stranice, treba koristi “computed” svojstvo (jer dobijamo na perfomansama zbog keširanja). Medjutim ako logika zahteva ponovni proračun pri svakom renderovanju stranice tj. pri bilo kakvoj promeni (ne samo promeni zavisnosti), onda koristite koristite “methods”.
NAPOMENA:
Ako se computed svojstvo koristi u okviru duplih vitičastih zagrada tj. ako se izvršava interpolacija JavaScript izraza, onda se samo navodi naziv “computed” svojstva (bez zagrada koje označavaju pozivanje i izvršavanje funkcije)
npr.
{{ nekoComputedSvojstvo }}
Ovo je još jedna sličnost sa “data” svojstvom jer “computed” svojstvo uvek vraća neku vrednost, stoga praktično mi očekujemo da se na mestu interpolacije štampa ta pripremljena (keširana) vrednost.
Primer
See the Pen
Computed Vue by Web programiranje (@chos)
on CodePen.
watch
Svojstvo “watch” pruža dodatni nivo kontrole, i omogućavaju nam da pratimo promene u modelu (data). Funkcije unutar “watch” objekta se aktiviraju samo kada se promeni određeno svojstvo u okviru data objekta. Treba naglasiti da “watched” svojstvo može da prati promene samo na jednom svojstvu
1 2 3 4 5 6 7 8 9 10 11 12 13 |
new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar', fullName: 'Foo Bar' }, watch: { firstName: function (val) { this.fullName = val + ' ' + this.lastName } } }) |
NAPOMENA:
Naziv watchera mora biti isti kao naziv data svojstva čiju promenu prati. Kroz parametar watch funkcije se prosledjuje promenjena vrednost data svojstva koju “nadgledamo”
Deep watch
Da bi smo pratili nestovana (ugnježdena) svojstva nekog objekta, potrebno je da definišemo vrednost parametra “deep” na “true”:
1 2 3 4 5 6 7 8 |
watch: { nekoSvojstvo: { handler: function () { ... }, deep: true } } |
Kada koristiti watch svojstvo?
“Watch” svojstva su specifičnija od computed svojstava i samim tim im je uže polje delovanja pa se i redje koriste. Koristite ih kada je potrebno da izvršite neku logiku nakon promene odredjenog child svojstva u okviru “data” objeka, pri čemu je željana akcija:
- asihrona operacija
- proračun tzv. medjurezultata
- dodatno smanjivanje broja aktiviranja odredjenih operacija (npr. debounce nad input dogadjajem)
Pored pomenutih slučajeva možemo primeniti watch i za mnoge druge funkcionalnosti ali to treba dobro proceniti, jer iako je izvršavanje neke funkcionalnost sa “watch” svojstvom izvodljivo, to ne znači da je i preporučljivo, jer može biti komplikovanije nego da koristimo “computed” svojstvo. Zaključak je da “watch” svojstvo treba koristiti tek kada “computed” svojstva ne mogu rešiti vaš problem.
Primer
U ovome primeru je prikazana situacija kada problem ne možemo da rešimo sa “computed” svojstvom. Jedan od razloga za korišćenje “watch” svojstva u ovome primeru je izvršavanje asihrone operacije unutar nje, a drugi je definisanje medjurezulta (answer), dok se ne dobije finalni odgovor. Ni jedan od ovih zadataka ne bi mogao da se uradi sa “computed” svojstvom.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
new Vue({ el: '#watch-example', data: { question: '', answer: 'I cannot give you an answer until you ask a question!' }, watch: { question: function (newQuestion, oldQuestion) { this.answer = 'Waiting for you to stop typing...' this.nekiAsinhroniZahtev() } }, . . . }) |
Primer
U ovome primeru koristimo svojstvo “searchQuery” sa kojim pratimo promenu istoimenog data svojstva, nakon čega upućujemo asinhroni zahtev serveru:
See the Pen Watch svojstvo za asinhroni zahtev serveru by Web programiranje (@chos) on CodePen.
Primena kroz primer
Kroz ovaj primer ću pokušati da objasnim primenu svakog od ovih važnih svojstava.
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 26 27 |
var vm = new Vue({ el: '#welcome', data: { message: 'Hello', name: 'World', nameEdits: 0 }, methods: { numRenders: function () { console.log('Page rendered') } }, computed: { welcomeMessage: function () { return this.message + ' ' + this.name } }, watch: { name: function () { if (this.message.toLowerCase() === 'reset') { this.nameEdits = 0 } else { this.nameEdits += 1 } } } }) |
a) methods sekcija
Funkcija “numRenders” iz “methods” sekcije će biti pozvana sa svakim rerenderom. Dakle, kad god se bilo šta ažurira na UI-u, poziva se funkcija “numRenders”.
b) computed sekcija
U “computed” sekciji će welcomeMessage će se pozvati samo kada se promeni “message” ili “name”, jer zavisi od te dve stvari. Dakle, ako se promeni bilo koja od drugih promenjivih kao što je “nameEdits”, “welcomeMessage” naša funkcija u “computed” sekciji neće biti ponovo pozvana, jer ne zavisi od njih.
c) watch sekcija
Funkcija “name” u “watch” sekciji prati samo promene vrednosti “name” iz “data” objekta. To znači da kad god se promeni “name”, pozove se naša funkcija koja ažurira i menja vrednost “nameEdits”. Ako se promeni bilo koja od drugih promenjivih iz “data” objekta “nameEdits” ili “message” naša funkcija u neće biti ponovo pozvana, jer njih ne prati.
Odlicno ljudi, hvala vam! Ja neko vreme vec pomalo uci vue.js i ovo mi je sad da kazem jednostavno, al bilo bi mi lakse da sam na pocetku imao vasa objasnjenja.
Kao prvo, stvarno odlican sajt!
Drugo, krivo su opisane methods, one se ne izvrsavaju svaki put kad se promjeni DOM ili komponenta ucita. To su obicne metode koje imaju pristup this Vue instanci a pozivaju se kad ih netko izricito pozove.
Hvala Janko na komentaru, baš mi znači. Moram da priznam da sam imao dosta nedoumica kada sam proučavo kako Vue.js tretira metode, jer je dokumentacija o metodama oskudna. Ali čitajući dokumentaciju izmedju redova i na osnovu drugih članaka u vezi sa Vue.js sam došao do zaključka da se u nekim slučajevima metode stvarno izvršavaju češće nego što izgleda na prvi pogled. Dao si mi podstrek da još jednom prodjem kroz ovu tematiku i ipak malo bolje objasnim na šta sam mislio i to potkrepim jednim primerom.
Veliki pozdrav
A da, imas pravo. To je ova magija koju Vue izvodi https://vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods
Taj dio je malo neobican i treba ga dobro prouciti jer moze izazvati bugove u kodu.