Poznajemy Vue, krok po kroku. Tym razem poznajemy, czym są methods i jak ich używać. Do dzieła.
Ok, nasza apka:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://unpkg.com/vue@3.4.9/dist/vue.global.js" defer></script>
<script src="app3.js" defer></script>
</head>
<body>
<div id="app">
<p>Random number: {{Math.random()}}</p>
</div>
</body>
</html>
Używamy tutaj funkcji wewnątrz nawiasów wąsatych jak widać. Oczywiście, potrzebna jeszcze część JavaScriptowa, inaczej to po prostu tekst:
const app = Vue.createApp({
data() {
return {
counter: 0
};
},
});
app.mount('#app');
Ok, fajnie. Ale mamy też takie coś, jak methods. Dodajmy metodę increment:
const app = Vue.createApp({
data() {
return {
counter: 0
};
},
methods: {
increment(){
this.counter++;
}
},
});
app.mount('#app');
This wskazuje na obiekt data, na zmienne w tym obiekcie. Ok, teraz markup:
<div id="app">
<p>Random number: {{Math.random()}}</p>
<p>Counter: {{counter}}</p>
<button @click="increment">+ 1</button>
</div>
Counter działa bez zarzutu, ale możemy zaobserwować, że za każdym jego użyciem Math.random też się wykonuje. Specjalnie takie przykłady tworzę, abyśmy oswoili się z tym, jak działają frameworki frontendowe, jakie mają ograniczenia.
Jest tak – każdy re-render sprawia, że metody są odpalane. Możemy to sprawdzić, dodajmy ten kod:
const app = Vue.createApp({
data() {
return {
counter: 0,
name: "John"
};
},
methods: {
increment(){
this.counter++;
},
fullname(){
console.log("I run");
return this.name + " Doe";
}
},
});
app.mount('#app');
Ok, pobawmy się guzikiem do inkrementacji. Żadnego i run nie będzie, tylko random będzie się wywoływać. Teraz jednak zmieńmy markup:
<div id="app">
<p>Random number: {{Math.random()}}</p>
<p>Counter: {{counter}}</p>
<p>Fullname: {{fullname()}}</p>
<button @click="increment">+ 1</button>
</div>
Teraz, za każdym kliknięciem zmieniającym counter (którego nowa wersja jest zapisywana w data) zobaczymy, że fullname również jest odpalane, choć wcale nie musi być, jego zależności (czyli name) się nie zmieniły.
Mimo wszystko – re-render (wymuszony przez zmianę countera, który jest wyświetlany) sprawia, że Vue musi obliczyć sobie wartość fullname od nowa.
To są zupełnie nowe koncepty, w backendzie tego nie mieliśmy. Cóż, przyzwyczajajmy się. Jest sposób, aby tego uniknąć, tzw. computed properties, ale o tym za chwilę.
Na razie sposób na setTimeout, który zmienia coś z data:
methods: {
increment(){
this.counter++;
},
fullname(){
console.log("I run");
return this.name + " Doe";
},
incrementDelayed(){
let that = this;
setTimeout(() => {
that.counter++;
}, 3000);
}
},
Stara sztuczka JavaScriptowców, nie ma nic z Vue wspólnego, jeżeli tego nie znamy, to wstyd. Użyjmy w markupie:
<button @click="increment">+ 1</button>
<button v-on:click="incrementDelayed">+ 1 delayed</button>
Dyrektywa v-on to po prostu wydłużona wersja @click. Nie ma znaczenia, czego używamy:
<button v-on:click="increment">+ 1</button>
<button @click="incrementDelayed">+ 1 delayed</button>
Oczywiście po tych 3 sekundach nastąpi zmiana countera (+1), która wymusza re-render, który wymusza ponowne wylosowanie liczby oraz ponowne obliczenie fullname.
Więcej Vue już wkrótce.