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.