Kolejny krok w nauce frameworka frontendowego Vue.js. Do dzieła.

Przypomnijmy sobie poprzedni markup:

<p>Random number: {{Math.random()}}</p>
<p>Counter: {{counter}}</p>
<p>Fullname: {{fullname()}}</p>
<button v-on:click="increment">+ 1</button>
<button @click="incrementDelayed">+ 1 delayed</button>

Przypomnijmy sobie poprzedni VueApp:

const app = Vue.createApp({
    data() {
      return {
        counter: 0,
        name: "John"
      };
    },
     methods: {
        increment(){
            this.counter++;
        },
        fullname(){
            console.log("I run");
            return this.name + " Doe";
        },
        incrementDelayed(){
            let that = this;
            
            setTimeout(() => {
                that.counter++;
            }, 3000);
        }
    },

  });
  
app.mount('#app');

Pamiętamy, że metody zbindowane do eventów były odpalane, gdy eventy miały miejsce. Metody używane w nawiasach klamrowych były odpalane przy każdym re-renderze, nawet jeżeli w ich zależnościach nic się nie zmieniło, to np. fullname było odpalane.

Ok, teraz nowa rzecz, computed property:

const app = Vue.createApp({
    data() {
      return {
        counter: 0,
        name: "John"
      };
    },
    methods: {
        increment(){
            this.counter++;
        },
        
        incrementDelayed(){
            let that = this;
            
            setTimeout(() => {
                that.counter++;
            }, 3000);
        }
    },
    computed: {
        fullname(){
            console.log("I run");
            return this.name + " Doe";
        },
    }

  });
  
app.mount('#app');

Dla żartu się to property nie nazywa, zatem wywalamy wywołanie funkcji z fullname:

<div id="app">
        <p>Random number: {{Math.random()}}</p>
        <p>Counter: {{counter}}</p>
        <p>Fullname: {{fullname}}</p>
        <button v-on:click="increment">+ 1</button>
        <button @click="incrementDelayed">+ 1 delayed</button>
</div>

Teraz, choć mają miejsce różne re-rendery (gdy spamujemy guziki +1) to zależności computed property fullname (czyli this.name) się nie zmieniają, zatem nie ma sensu obliczać non stop tego fullname. Taki odpowiednik useEffect z Reacta.

Oczywiście polecam wszystkim sprawdzać wszystko samemu:

const app = Vue.createApp({
    data() {
      return {
        counter: 0,
        name: "John"
      };
    },
    methods: {
        increment(){
            this.counter++;
        },
        
        incrementDelayed(){
            let that = this;
            
            setTimeout(() => {
                that.counter++;
                that.name = "Jane"
            }, 3000);
        }
    },
    computed: {
        fullname(){
            console.log("I run");
            return this.name + " Doe";
        },
    }

  });
  
app.mount('#app');

Teraz fullname zostanie ponownie odpalone i obliczone, jak się zmieni na Jane. Co ciekawe – gdy już mamy Jane, to kolejne klikanie w delayed nie zmienia nic, ta metoda co prawda dotyka name (nadpisuje), ale nadpisuje na to samo, zatem zależność, która decyduje o tym, czy computed property zostanie ponownie obliczone, się nie zmienia.

Coś jak tablica zależności w useEffect w React. Więcej Vue niedługo.