Poznajemy różnice pomiędzy watcherami a computed properties. Kolejna łatwa lekcja o Vue.js. Do dzieła.
Ok, poprzednio nasz markup wyglądał tak:
<div id="app">
<input type="text" :value="name" ref="ipt" @input="onInput"/>
<p v-if="showHello">Hello <span v-text="name"></span></p>
</div>
Nasz JS wyglądał tak:
const app = Vue.createApp({
data(){
return {
name: "",
showHello: false
};
},
methods: {
onInput(){
this.name = this.$refs.ipt.value;
}
},
watch: {
name(value){
if(value.length > 0)
this.showHello = true;
else
this.showHello = false;
}
}
});
app.mount('#app');
Data zawiera zmienne, methods metodę odpalaną eventem (każda inna odpala się przy każdym re-renderze), jeszcze $refs używaliśmy, watcher zaś robi to, czym się zajmuje – obserwuje jedną zmienną, przyjmując jej nową wartość i wywołując się za każdym razem, gdy ta zmienna się zmieni i zmieniając coś, najczęściej zupełnie z tą zmienną niepowiązanego (jak tutaj showHello).
Ok, a teraz wyobraźmy sobie, że nie chcemy tego hello ukrywać, tylko na pusty name mieć hello stranger. Nasz markup:
<div id="app">
<input type="text" :value="name" ref="ipt" @input="onInput"/>
<p>Hello {{username}}</p>
</div>
Nasz JS:
const app = Vue.createApp({
data(){
return {
name: "",
showHello: false
};
},
methods: {
onInput(){
this.name = this.$refs.ipt.value;
}
},
computed: {
username(){
if(this.name === "")
return "Stranger"
return this.name;
}
}
});
app.mount('#app');
Różnica jest prosta:
- Computed property tworzy nowe property o nowej nazwie (tutaj username)
- Watcher obserwuje istniejącą zmienną z data (ma taką samą nazwę)
- Computed property może odnosić się do data przez this
- Każda rzecz, której computed property używa przez this zostaje dopisana do tablicy zależności tego property
- Computed property będzie odpalane tylko wtedy, gdy zmieni się któraś z jego zależności (tutaj tylko name), inaczej nie będzie wyliczane przy każdym re-renderze (jak metody z methods, które są używane poza eventami)
- Computed property może obserwować zmiany wielu zmiennych, ale zwraca nową wartość property
- Watcher może obserwować tylko jedną zmienną na raz (nazwa metody watchera odpowiada nazwie zmiennej z data)
- Watcher niczego nie zwraca, przyjmuje nową wartość tej jednej zmiennej, której zmiany obserwuje, może za to dokonywać wielu modyfikacji w wielu innych miejscach
Tak to wygląda, trzeba do tego przywyknąć.
Teraz słowo o methods i inline methods (te w nawiasach wąsatych). Najlepiej sprawdźmy w działaniu ten kod:
<div id="app">
<p>Random number: {{Math.random()}}</p>
<input type="text" :value="name" ref="ipt" @input="onInput"/>
<p>Hello {{username}}</p>
</div>
Przy każdym re-renderze (czyli w zasadzie każdym wciśnięciu klawisza, także backspace jeśli name nie jest puste) mamy nowy losowy numer. Methods też tak działają.
Możemy to jednak zablokować przez v-once:
<div id="app">
<p v-once>Random number: {{Math.random()}}</p>
<input type="text" :value="name" ref="ipt" @input="onInput"/>
<p>Hello {{username}}</p>
</div>
Teraz metoda random wywoła się jeden raz i już tak zostanie.