[Medium] π ΠΡΠ½ΠΎΠ²Ρ Vue ΠΈ API
1. ΠΠΎΠΆΠ΅ΡΠ΅ Π»ΠΈ Π²Ρ ΠΎΠΏΠΈΡΠ°ΡΡ ΠΎΡΠ½ΠΎΠ²Π½ΡΠ΅ ΠΏΡΠΈΠ½ΡΠΈΠΏΡ ΠΈ ΠΏΡΠ΅ΠΈΠΌΡΡΠ΅ΡΡΠ²Π° ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊΠ° Vue?β
ΠΠΏΠΈΡΠΈΡΠ΅ ΠΎΡΠ½ΠΎΠ²Π½ΡΠ΅ ΠΏΡΠΈΠ½ΡΠΈΠΏΡ ΠΈ ΡΠΈΠ»ΡΠ½ΡΠ΅ ΡΡΠΎΡΠΎΠ½Ρ Vue.
ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ ΠΏΡΠΈΠ½ΡΠΈΠΏΡβ
Vue β ΠΏΡΠΎΠ³ΡΠ΅ΡΡΠΈΠ²Π½ΡΠΉ JavaScript-ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊ. ΠΠ³ΠΎ ΠΊΠ»ΡΡΠ΅Π²ΡΠ΅ ΠΊΠΎΠ½ΡΠ΅ΠΏΡΠΈΠΈ Π²ΠΊΠ»ΡΡΠ°ΡΡ:
1. Virtual DOMβ
Vue ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ Virtual DOM diffing Π΄Π»Ρ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΈΠ·ΠΌΠ΅Π½ΡΠ½Π½ΡΡ ΡΠ°ΡΡΠ΅ΠΉ ΡΠ΅Π°Π»ΡΠ½ΠΎΠ³ΠΎ DOM.
// ΡΠΏΡΠΎΡΡΠ½Π½Π°Ρ ΠΊΠΎΠ½ΡΠ΅ΠΏΡΠΈΡ Virtual DOM
const vnode = {
tag: 'div',
props: { class: 'container' },
children: [
{ tag: 'h1', children: 'Hello' },
{ tag: 'p', children: 'World' },
],
};
2. Π Π΅Π°ΠΊΡΠΈΠ²Π½ΠΎΠ΅ ΡΠ²ΡΠ·ΡΠ²Π°Π½ΠΈΠ΅ Π΄Π°Π½Π½ΡΡ β
Π Π΅Π°ΠΊΡΠΈΠ²Π½ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡΡ UI. Π‘ ΠΏΡΠΈΠ²ΡΠ·ΠΊΠ°ΠΌΠΈ ΡΠΎΡΠΌ (v-model) Π²Π²ΠΎΠ΄ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΡΠ°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅.
<template>
<input v-model="message" />
<p>{{ message }}</p>
</template>
<script setup>
import { ref } from 'vue';
const message = ref('Hello Vue');
</script>
3. ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ½Π°Ρ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ°β
UI ΡΠ°Π·Π΄Π΅Π»ΡΠ΅ΡΡΡ Π½Π° ΠΏΠ΅ΡΠ΅ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΡΠ΅, ΡΠ΅ΡΡΠΈΡΡΠ΅ΠΌΡΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ Ρ ΠΈΠ·ΠΎΠ»ΠΈΡΠΎΠ²Π°Π½Π½ΡΠΌΠΈ ΠΎΡΠ²Π΅ΡΡΡΠ²Π΅Π½Π½ΠΎΡΡΡΠΌΠΈ.
<!-- Button.vue -->
<template>
<button @click="handleClick">
<slot></slot>
</button>
</template>
<script setup>
const emit = defineEmits(['click']);
const handleClick = () => emit('click');
</script>
4. Π₯ΡΠΊΠΈ ΠΆΠΈΠ·Π½Π΅Π½Π½ΠΎΠ³ΠΎ ΡΠΈΠΊΠ»Π°β
Π₯ΡΠΊΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡ Π²ΡΠΏΠΎΠ»Π½ΡΡΡ Π»ΠΎΠ³ΠΈΠΊΡ Π½Π° ΡΡΠ°ΠΏΠ°Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ/ΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ/ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ/ΡΠ°Π·ΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ.
<script setup>
import { onMounted, onUpdated, onUnmounted } from 'vue';
onMounted(() => {
console.log('ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ ΡΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½');
});
onUpdated(() => {
console.log('ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ ΠΎΠ±Π½ΠΎΠ²Π»ΡΠ½');
});
onUnmounted(() => {
console.log('ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ ΡΠ°Π·ΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½');
});
</script>
5. Π‘ΠΈΡΡΠ΅ΠΌΠ° Π΄ΠΈΡΠ΅ΠΊΡΠΈΠ²β
ΠΠΈΡΠ΅ΠΊΡΠΈΠ²Ρ Vue ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΡΡ Π΄Π΅ΠΊΠ»Π°ΡΠ°ΡΠΈΠ²Π½ΡΡ Π»ΠΎΠ³ΠΈΠΊΡ UI (v-if, v-for, v-bind, v-model ΠΈ Ρ.Π΄.).
<template>
<div v-if="isVisible">ΠΠΈΠ΄ΠΈΠΌΠΎΠ΅ ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ΅</div>
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
<img :src="imageUrl" :alt="imageAlt" />
<input v-model="username" />
</template>
6. Π‘ΠΈΠ½ΡΠ°ΠΊΡΠΈΡ ΡΠ°Π±Π»ΠΎΠ½ΠΎΠ²β
Π¨Π°Π±Π»ΠΎΠ½Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡ ΠΈΠ½ΡΠ΅ΡΠΏΠΎΠ»ΡΡΠΈΡ ΠΈ Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΡ, ΡΠΎΡ ΡΠ°Π½ΡΡ ΡΠΈΡΠ°Π΅ΠΌΠΎΡΡΡ ΡΠ°Π·ΠΌΠ΅ΡΠΊΠΈ.
<template>
<div>
<p>{{ message }}</p>
<p>{{ count + 1 }}</p>
<p>{{ formatDate(date) }}</p>
</div>
</template>
Π‘ΠΈΠ»ΡΠ½ΡΠ΅ ΡΡΠΎΡΠΎΠ½Ρ Vue (ΡΠ°ΡΡΠΎ ΡΡΠ°Π²Π½ΠΈΠ²Π°Π΅ΡΡΡ Ρ React)β
1. ΠΠΎΠ»Π΅Π΅ Π½ΠΈΠ·ΠΊΠΈΠΉ ΠΏΠΎΡΠΎΠ³ Π²Ρ ΠΎΠ΄Π°β
ΠΠ΄Π½ΠΎΡΠ°ΠΉΠ»ΠΎΠ²ΡΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ (template/script/style) ΠΈΠ½ΡΡΠΈΡΠΈΠ²Π½Ρ Π΄Π»Ρ ΠΌΠ½ΠΎΠ³ΠΈΡ
ΠΊΠΎΠΌΠ°Π½Π΄.
2. ΠΡΡΡΠΎΠ΅Π½Π½ΡΠ΅ Π΄Π΅ΠΊΠ»Π°ΡΠ°ΡΠΈΠ²Π½ΡΠ΅ Π΄ΠΈΡΠ΅ΠΊΡΠΈΠ²Ρβ
Π’ΠΈΠΏΠΈΡΠ½ΡΠ΅ Π·Π°Π΄Π°ΡΠΈ UI Π»Π°ΠΊΠΎΠ½ΠΈΡΠ½Ρ Ρ Π΄ΠΈΡΠ΅ΠΊΡΠΈΠ²Π°ΠΌΠΈ.
3. ΠΡΠΎΡΡΠΎΠ΅ Π΄Π²ΡΡΡΠΎΡΠΎΠ½Π½Π΅Π΅ ΡΠ²ΡΠ·ΡΠ²Π°Π½ΠΈΠ΅ ΡΠΎΡΠΌβ
v-model ΠΏΡΠ΅Π΄Π»Π°Π³Π°Π΅Ρ ΠΏΠ΅ΡΠ²ΠΎΠΊΠ»Π°ΡΡΠ½ΡΠΉ ΠΏΠ°ΡΡΠ΅ΡΠ½ Π΄Π»Ρ ΡΠΈΠ½Ρ
ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ Π²Π²ΠΎΠ΄Π°.
4. Π§ΡΡΠΊΠΎΠ΅ ΡΠ°Π·Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΡΠ°Π±Π»ΠΎΠ½Π° ΠΈ Π»ΠΎΠ³ΠΈΠΊΠΈβ
ΠΠ΅ΠΊΠΎΡΠΎΡΡΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ ΠΏΡΠ΅Π΄ΠΏΠΎΡΠΈΡΠ°ΡΡ ΡΡΡΡΠΊΡΡΡΡ Ρ ΠΏΡΠΈΠΎΡΠΈΡΠ΅ΡΠΎΠΌ ΡΠ°Π±Π»ΠΎΠ½Π° ΠΏΠΎ ΡΡΠ°Π²Π½Π΅Π½ΠΈΡ Ρ ΠΏΠ°ΡΡΠ΅ΡΠ½Π°ΠΌΠΈ, Π½Π°ΡΡΡΠ΅Π½Π½ΡΠΌΠΈ JSX.
5. Π¦Π΅Π»ΠΎΡΡΠ½Π°Ρ ΠΎΡΠΈΡΠΈΠ°Π»ΡΠ½Π°Ρ ΡΠΊΠΎΡΠΈΡΡΠ΅ΠΌΠ°β
Vue Router + Pinia + ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΎΠ² Ρ ΠΎΡΠΎΡΠΎ ΡΠΎΠ³Π»Π°ΡΠΎΠ²Π°Π½Ρ.
2. ΠΠ±ΡΡΡΠ½ΠΈΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ v-model, v-bind ΠΈ v-htmlβ
ΠΠ±ΡΡΡΠ½ΠΈΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅
v-model,v-bindΠΈv-html.
v-model: Π΄Π²ΡΡΡΠΎΡΠΎΠ½Π½Π΅Π΅ ΡΠ²ΡΠ·ΡΠ²Π°Π½ΠΈΠ΅ Π΄Π»Ρ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ² ΡΠΎΡΠΌβ
<template>
<div>
<input v-model="message" />
<p>Π‘ΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅: {{ message }}</p>
<input type="checkbox" v-model="checked" />
<p>ΠΡΠΌΠ΅ΡΠ΅Π½ΠΎ: {{ checked }}</p>
<select v-model="selected">
<option value="A">ΠΠ°ΡΠΈΠ°Π½Ρ A</option>
<option value="B">ΠΠ°ΡΠΈΠ°Π½Ρ B</option>
</select>
<p>ΠΡΠ±ΡΠ°Π½ΠΎ: {{ selected }}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: '',
checked: false,
selected: 'A',
};
},
};
</script>
ΠΠΎΠ΄ΠΈΡΠΈΠΊΠ°ΡΠΎΡΡ v-modelβ
<input v-model.lazy="msg" />
<input v-model.number="age" type="number" />
<input v-model.trim="msg" />
v-bind: Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΠ°Ρ ΠΏΡΠΈΠ²ΡΠ·ΠΊΠ° Π°ΡΡΠΈΠ±ΡΡΠΎΠ²β
<template>
<div>
<div :class="{ active: isActive, 'text-danger': hasError }">ΠΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΠΈΠΉ ΠΊΠ»Π°ΡΡ</div>
<div :style="{ color: textColor, fontSize: fontSize + 'px' }">ΠΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΠΈΠΉ ΡΡΠΈΠ»Ρ</div>
<img :src="imageUrl" :alt="imageAlt" />
<a :href="linkUrl">ΠΠ΅ΡΠ΅ΠΉΡΠΈ ΠΏΠΎ ΡΡΡΠ»ΠΊΠ΅</a>
<div :data-id="userId" :data-name="userName"></div>
</div>
</template>
<script>
export default {
data() {
return {
isActive: true,
hasError: false,
textColor: 'red',
fontSize: 16,
imageUrl: 'https://example.com/image.jpg',
imageAlt: 'ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ',
linkUrl: 'https://example.com',
userId: 123,
userName: 'John',
};
},
};
</script>
Π‘ΠΎΠΊΡΠ°ΡΠ΅Π½ΠΈΠ΅ v-bindβ
<img v-bind:src="imageUrl" />
<img :src="imageUrl" />
<div v-bind="objectOfAttrs"></div>
v-html: ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³ ΡΡΡΠΎΠΉ HTML-ΡΡΡΠΎΠΊΠΈβ
<template>
<div>
<p>{{ rawHtml }}</p>
<p v-html="rawHtml"></p>
</div>
</template>
<script>
export default {
data() {
return {
rawHtml: '<span style="color: red">ΠΡΠ°ΡΠ½ΡΠΉ ΡΠ΅ΠΊΡΡ</span>',
};
},
};
</script>
ΠΡΠ΅Π΄ΡΠΏΡΠ΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΎ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈβ
ΠΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ v-html Π½Π°ΠΏΡΡΠΌΡΡ Π΄Π»Ρ Π½Π΅ΠΏΡΠΎΠ²Π΅ΡΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΎΠ³ΠΎ Π²Π²ΠΎΠ΄Π° (ΡΠΈΡΠΊ XSS).
<!-- Π½Π΅Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎ -->
<div v-html="userProvidedContent"></div>
<!-- Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½Π΅Π΅: ΡΠ°Π½ΠΈΡΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ΅ -->
<div v-html="sanitizedHtml"></div>
ΠΠΎΠ»Π΅Π΅ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΡΠΉ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ Ρ ΡΠ°Π½ΠΈΡΠ°ΠΉΠ·Π΅ΡΠΎΠΌβ
<script>
import DOMPurify from 'dompurify';
export default {
data() {
return {
userInput: '<img src=x onerror=alert("XSS")>',
};
},
computed: {
sanitizedHtml() {
return DOMPurify.sanitize(this.userInput);
},
},
};
</script>
ΠΡΠ°ΡΠΊΠΎΠ΅ ΡΡΠ°Π²Π½Π΅Π½ΠΈΠ΅β
| ΠΠΈΡΠ΅ΠΊΡΠΈΠ²Π° | ΠΠ°Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ | Π‘ΠΎΠΊΡΠ°ΡΠ΅Π½ΠΈΠ΅ | ΠΡΠΈΠΌΠ΅Ρ |
|---|---|---|---|
v-model | ΠΠ²ΡΡΡΠΎΡΠΎΠ½Π½Π΅Π΅ ΡΠ²ΡΠ·ΡΠ²Π°Π½ΠΈΠ΅ ΡΠΎΡΠΌ | ΠΠ΅Ρ | <input v-model="msg"> |
v-bind | ΠΠ΄Π½ΠΎΡΡΠΎΡΠΎΠ½Π½Π΅Π΅ ΡΠ²ΡΠ·ΡΠ²Π°Π½ΠΈΠ΅ Π°ΡΡΠΈΠ±ΡΡΠΎΠ² | : | <img :src="url"> |
v-html | Π Π΅Π½Π΄Π΅ΡΠΈΠ½Π³ ΡΡΡΠΎΠ³ΠΎ HTML | ΠΠ΅Ρ | <div v-html="html"></div> |
3. ΠΠ°ΠΊ ΠΏΠΎΠ»ΡΡΠΈΡΡ Π΄ΠΎΡΡΡΠΏ ΠΊ HTML-ΡΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΠΌ (Template Refs)?β
ΠΠ°ΠΊ ΠΌΠ°Π½ΠΈΠΏΡΠ»ΠΈΡΠΎΠ²Π°ΡΡ HTML-ΡΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΠΌΠΈ Π² Vue (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΡΡΡΠ°Π½ΠΎΠ²ΠΈΡΡ ΡΠΎΠΊΡΡ Π½Π° input)?
ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ template refs Π²ΠΌΠ΅ΡΡΠΎ document.querySelector Π² ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°Ρ
.
Options API (Vue 2 / Vue 3)β
<template>
<div>
<input ref="inputElement" />
<button @click="focusInput">Π£ΡΡΠ°Π½ΠΎΠ²ΠΈΡΡ ΡΠΎΠΊΡΡ</button>
</div>
</template>
<script>
export default {
methods: {
focusInput() {
this.$refs.inputElement.focus();
},
},
mounted() {
console.log(this.$refs.inputElement);
},
};
</script>
Composition API (Vue 3)β
<template>
<div>
<input ref="inputElement" />
<button @click="focusInput">Π£ΡΡΠ°Π½ΠΎΠ²ΠΈΡΡ ΡΠΎΠΊΡΡ</button>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const inputElement = ref(null);
const focusInput = () => {
inputElement.value?.focus();
};
onMounted(() => {
console.log(inputElement.value);
});
</script>
ΠΠ°ΠΌΠ΅ΡΠ°Π½ΠΈΡ:
- ΠΠΌΡ ref Π² ΡΠ°Π±Π»ΠΎΠ½Π΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡΡ Ρ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ Π² ΡΠΊΡΠΈΠΏΡΠ΅
- ΠΠΎΡΡΡΠΏ ΠΏΠΎΡΠ»Π΅ ΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ (
onMounted/mounted) - ΠΠ½ΡΡΡΠΈ
v-forrefs ΡΡΠ°Π½ΠΎΠ²ΡΡΡΡ ΠΌΠ°ΡΡΠΈΠ²Π°ΠΌΠΈ
4. Π ΡΡΠΌ ΡΠ°Π·Π½ΠΈΡΠ° ΠΌΠ΅ΠΆΠ΄Ρ v-show ΠΈ v-if?β
ΠΠ±ΡΡΡΠ½ΠΈΡΠ΅ ΡΠ°Π·Π»ΠΈΡΠΈΡ ΠΌΠ΅ΠΆΠ΄Ρ
v-showΠΈv-if.
Π‘Ρ ΠΎΠ΄ΡΡΠ²ΠΎβ
ΠΠ±Π° ΡΠΏΡΠ°Π²Π»ΡΡΡ Π²ΠΈΠ΄ΠΈΠΌΠΎΡΡΡΡ Π½Π° ΠΎΡΠ½ΠΎΠ²Π΅ ΡΡΠ»ΠΎΠ²ΠΈΠΉ.
<template>
<div v-if="isVisible">ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ v-if</div>
<div v-show="isVisible">ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ v-show</div>
</template>
Π Π°Π·Π»ΠΈΡΠΈΡβ
1) ΠΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ DOMβ
v-if: ΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅/ΡΠ°Π·ΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ·Π»Π°v-show: Π²ΡΠ΅Π³Π΄Π° ΡΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½; ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ°Π΅Ρ CSSdisplay
2) ΠΡΠΎΡΠΈΠ»Ρ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈβ
v-if: Π½ΠΈΠ·ΠΊΠ°Ρ Π½Π°ΡΠ°Π»ΡΠ½Π°Ρ ΡΡΠΎΠΈΠΌΠΎΡΡΡ ΠΏΡΠΈ false, Π²ΡΡΠΎΠΊΠ°Ρ ΡΡΠΎΠΈΠΌΠΎΡΡΡ ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΡv-show: Π²ΡΡΠΎΠΊΠ°Ρ Π½Π°ΡΠ°Π»ΡΠ½Π°Ρ ΡΡΠΎΠΈΠΌΠΎΡΡΡ, Π½ΠΈΠ·ΠΊΠ°Ρ ΡΡΠΎΠΈΠΌΠΎΡΡΡ ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ
3) ΠΠ»ΠΈΡΠ½ΠΈΠ΅ Π½Π° ΠΆΠΈΠ·Π½Π΅Π½Π½ΡΠΉ ΡΠΈΠΊΠ»β
v-ifΠ·Π°ΠΏΡΡΠΊΠ°Π΅Ρ ΠΏΠΎΠ»Π½ΡΠΉ ΠΆΠΈΠ·Π½Π΅Π½Π½ΡΠΉ ΡΠΈΠΊΠ» Π΄ΠΎΡΠ΅ΡΠ½ΠΈΡ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ² ΠΏΡΠΈ ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΠΈv-showΠ½Π΅ ΡΠ°Π·ΠΌΠΎΠ½ΡΠΈΡΡΠ΅Ρ; Π½Π΅Ρ ΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ/ΡΠ°Π·ΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΏΡΠΈ ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΠΈ
4) Π‘ΡΠΎΠΈΠΌΠΎΡΡΡ Π½Π°ΡΠ°Π»ΡΠ½ΠΎΠ³ΠΎ ΡΠ΅Π½Π΄Π΅ΡΠ°β
ΠΠ»Ρ ΡΡΠΆΡΠ»ΡΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ², ΠΈΠ·Π½Π°ΡΠ°Π»ΡΠ½ΠΎ ΡΠΊΡΡΡΡΡ :
v-if="false": ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ Π½Π΅ ΡΠ΅Π½Π΄Π΅ΡΠΈΡΡΡv-show="false": ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ ΡΠ΅Π½Π΄Π΅ΡΠΈΡΡΡ, Π½ΠΎ ΡΠΊΡΡΡ
5) ΠΠΎΠΌΠ±ΠΈΠ½Π°ΡΠΈΠΈ Π΄ΠΈΡΠ΅ΠΊΡΠΈΠ²β
v-ifΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρv-else-if/v-elsev-showβ Π½Π΅Ρ
ΠΠΎΠ³Π΄Π° ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΊΠ°ΠΆΠ΄ΡΠΉβ
ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ v-if, ΠΊΠΎΠ³Π΄Π°β
- Π£ΡΠ»ΠΎΠ²ΠΈΠ΅ ΠΌΠ΅Π½ΡΠ΅ΡΡΡ ΡΠ΅Π΄ΠΊΠΎ
- ΠΠ°ΡΠ°Π»ΡΠ½ΠΎΠ΅ false Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΈΠ·Π±Π΅ΠΆΠ°ΡΡ ΡΡΠΎΠΈΠΌΠΎΡΡΠΈ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³Π°
- ΠΠ°ΠΌ Π½ΡΠΆΠ½Ρ ΡΡΠ»ΠΎΠ²Π½ΡΠ΅ Π²Π΅ΡΠΊΠΈ Ρ
v-else - ΠΡΠΆΠ½Ρ ΠΏΠΎΠ±ΠΎΡΠ½ΡΠ΅ ΡΡΡΠ΅ΠΊΡΡ ΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ/ΡΠ°Π·ΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ
ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ v-show, ΠΊΠΎΠ³Π΄Π°β
- ΠΠΈΠ΄ΠΈΠΌΠΎΡΡΡ ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ°Π΅ΡΡΡ ΡΠ°ΡΡΠΎ
- ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΎΡΡΠ°Π²Π°ΡΡΡΡ ΡΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠΌ Π΄Π»Ρ ΡΠΎΡ ΡΠ°Π½Π΅Π½ΠΈΡ Π²Π½ΡΡΡΠ΅Π½Π½Π΅Π³ΠΎ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ
- ΠΠΎΠ²ΡΠΎΡΠ½ΠΎΠ΅ ΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π΅ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ
Π‘Π²ΠΎΠ΄Π½Π°Ρ ΡΠ°Π±Π»ΠΈΡΠ°β
| Π₯Π°ΡΠ°ΠΊΡΠ΅ΡΠΈΡΡΠΈΠΊΠ° | v-if | v-show |
|---|---|---|
| ΠΠ°ΡΠ°Π»ΡΠ½Π°Ρ ΡΡΠΎΠΈΠΌΠΎΡΡΡ | ΠΠΈΠΆΠ΅ (ΠΏΡΠΈ false) | ΠΡΡΠ΅ (Π²ΡΠ΅Π³Π΄Π° ΡΠ΅Π½Π΄Π΅ΡΠΈΡΡΡ) |
| Π‘ΡΠΎΠΈΠΌΠΎΡΡΡ ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ | ΠΡΡΠ΅ | ΠΠΈΠΆΠ΅ |
| Lifecycle ΠΏΡΠΈ ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΠΈ | ΠΠ° | ΠΠ΅Ρ |
| ΠΡΡΡΠ΅ Π΄Π»Ρ | Π Π΅Π΄ΠΊΠΈΡ ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ | Π§Π°ΡΡΡΡ ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ |
ΠΠ½Π΅ΠΌΠΎΠ½ΠΈΠΊΠ°β
v-if: Β«ΡΠ΅Π½Π΄Π΅ΡΠΈΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΡΠΈ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎΡΡΠΈΒ»v-show: Β«ΡΠ΅Π½Π΄Π΅ΡΠΈΡΡ ΠΎΠ΄ΠΈΠ½ ΡΠ°Π·, ΡΠΊΡΡΠ²Π°ΡΡ/ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°ΡΡ ΡΠ΅ΡΠ΅Π· CSSΒ»
5. Π ΡΡΠΌ ΡΠ°Π·Π½ΠΈΡΠ° ΠΌΠ΅ΠΆΠ΄Ρ computed ΠΈ watch?β
Π ΡΡΠΌ ΡΠ°Π·Π½ΠΈΡΠ° ΠΌΠ΅ΠΆΠ΄Ρ
computedΠΈwatch?
ΠΠ±Π° ΡΠ΅Π°Π³ΠΈΡΡΡΡ Π½Π° ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ, Π½ΠΎ ΡΠ΅ΡΠ°ΡΡ ΡΠ°Π·Π½ΡΠ΅ Π·Π°Π΄Π°ΡΠΈ.
computedβ
ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ Ρ Π°ΡΠ°ΠΊΡΠ΅ΡΠΈΡΡΠΈΠΊΠΈβ
- ΠΡΡΠΈΡΠ»ΡΠ΅Ρ Π½ΠΎΠ²ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅ ΠΈΠ· ΡΡΡΠ΅ΡΡΠ²ΡΡΡΠ΅Π³ΠΎ ΡΠ΅Π°ΠΊΡΠΈΠ²Π½ΠΎΠ³ΠΎ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ
- ΠΠ΅ΡΠΈΡΡΠ΅ΡΡΡ Π΄ΠΎ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ
- Π‘ΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΠΉ ΠΈ ΠΎΡΠΈΠ΅Π½ΡΠΈΡΠΎΠ²Π°Π½ Π½Π° Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅
- ΠΠ°ΠΏΡΡΠΌΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π² ΡΠ°Π±Π»ΠΎΠ½Π΅
Π’ΠΈΠΏΠΈΡΠ½ΡΠ΅ ΡΠ»ΡΡΠ°ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡβ
<script setup>
import { ref, computed } from 'vue';
const firstName = ref('John');
const lastName = ref('Doe');
const email = ref('JOHN@EXAMPLE.COM');
const cart = ref([
{ id: 1, name: 'Apple', price: 2, quantity: 3 },
{ id: 2, name: 'Banana', price: 1, quantity: 5 },
]);
const searchText = ref('');
const items = ref([
{ id: 1, name: 'Apple' },
{ id: 2, name: 'Banana' },
{ id: 3, name: 'Cherry' },
]);
const fullName = computed(() => `${firstName.value} ${lastName.value}`);
const emailLowerCase = computed(() => email.value.toLowerCase());
const cartTotal = computed(() =>
cart.value.reduce((total, item) => total + item.price * item.quantity, 0)
);
const filteredItems = computed(() =>
!searchText.value
? items.value
: items.value.filter((item) =>
item.name.toLowerCase().includes(searchText.value.toLowerCase())
)
);
</script>
ΠΡΠ΅ΠΈΠΌΡΡΠ΅ΡΡΠ²ΠΎ ΠΊΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡβ
<script setup>
import { computed, ref } from 'vue';
const items = ref(Array.from({ length: 1000 }, (_, index) => index));
const expensiveComputed = computed(() => {
console.log('computed Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΡΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ');
return items.value.reduce((sum, item) => sum + item, 0);
});
const expensiveMethod = () => {
console.log('ΠΌΠ΅ΡΠΎΠ΄ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ ΠΏΡΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ Π²ΡΠ·ΠΎΠ²Π΅');
return items.value.reduce((sum, item) => sum + item, 0);
};
</script>
Π€ΠΎΡΠΌΠ° getter + setterβ
<script setup>
import { computed, ref } from 'vue';
const firstName = ref('John');
const lastName = ref('Doe');
const fullName = computed({
get() {
return `${firstName.value} ${lastName.value}`;
},
set(newValue) {
const names = newValue.split(' ');
firstName.value = names[0] ?? '';
lastName.value = names[names.length - 1] ?? '';
},
});
</script>
watchβ
ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ Ρ Π°ΡΠ°ΠΊΡΠ΅ΡΠΈΡΡΠΈΠΊΠΈβ
- Π―Π²Π½ΠΎ Π½Π°Π±Π»ΡΠ΄Π°Π΅Ρ Π·Π° ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠΎΠΌ(Π°ΠΌΠΈ)
- ΠΡΠ΅Π΄Π½Π°Π·Π½Π°ΡΠ΅Π½ Π΄Π»Ρ ΠΏΠΎΠ±ΠΎΡΠ½ΡΡ ΡΡΡΠ΅ΠΊΡΠΎΠ²
- ΠΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΠ΅ ΡΠ°Π±ΠΎΡΠΈΠ΅ ΠΏΡΠΎΡΠ΅ΡΡΡ
- ΠΠΎΠΆΠ΅Ρ ΠΏΠΎΠ»ΡΡΠΈΡΡ Π΄ΠΎΡΡΡΠΏ ΠΊ
newValueΠΈoldValue
Π’ΠΈΠΏΠΈΡΠ½ΡΠ΅ ΡΠ»ΡΡΠ°ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡβ
<script setup>
import { ref, watch, onBeforeUnmount } from 'vue';
const searchQuery = ref('');
const searchResults = ref([]);
const isSearching = ref(false);
const username = ref('');
const usernameError = ref('');
const content = ref('');
const isSaving = ref(false);
const lastSaved = ref(null);
let searchTimer = null;
let saveTimer = null;
// 1) ΠΏΠΎΠΈΡΠΊ Ρ Π·Π°Π΄Π΅ΡΠΆΠΊΠΎΠΉ
watch(searchQuery, (newQuery, oldQuery) => {
clearTimeout(searchTimer);
if (!newQuery) {
searchResults.value = [];
return;
}
isSearching.value = true;
searchTimer = setTimeout(async () => {
try {
const response = await fetch(`/api/users?q=${newQuery}`);
searchResults.value = await response.json();
} finally {
isSearching.value = false;
}
}, 500);
});
// 2) ΠΏΠΎΠ±ΠΎΡΠ½ΡΠΉ ΡΡΡΠ΅ΠΊΡ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΠΈ
watch(username, (newUsername) => {
if (newUsername.length < 3) {
usernameError.value = 'ΠΠΌΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΡ Π½Π΅ ΠΌΠ΅Π½Π΅Π΅ 3 ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ²';
} else if (newUsername.length > 20) {
usernameError.value = 'ΠΠΌΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΡ Π½Π΅ Π±ΠΎΠ»Π΅Π΅ 20 ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ²';
} else if (!/^[a-zA-Z0-9_]+$/.test(newUsername)) {
usernameError.value =
'ΠΠΌΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΠΌΠΎΠΆΠ΅Ρ ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΡ ΡΠΎΠ»ΡΠΊΠΎ Π±ΡΠΊΠ²Ρ, ΡΠΈΡΡΡ ΠΈ Π½ΠΈΠΆΠ½Π΅Π΅ ΠΏΠΎΠ΄ΡΡΡΠΊΠΈΠ²Π°Π½ΠΈΠ΅';
} else {
usernameError.value = '';
}
});
// 3) ΠΏΠΎΠ±ΠΎΡΠ½ΡΠΉ ΡΡΡΠ΅ΠΊΡ Π°Π²ΡΠΎΡΠΎΡ
ΡΠ°Π½Π΅Π½ΠΈΡ
watch(content, (newContent) => {
clearTimeout(saveTimer);
saveTimer = setTimeout(async () => {
isSaving.value = true;
try {
await fetch('/api/save', {
method: 'POST',
body: JSON.stringify({ content: newContent }),
});
lastSaved.value = new Date().toLocaleTimeString();
} finally {
isSaving.value = false;
}
}, 1000);
});
onBeforeUnmount(() => {
clearTimeout(searchTimer);
clearTimeout(saveTimer);
});
</script>
ΠΠΏΡΠΈΠΈ watchβ
<script setup>
import { ref, watch } from 'vue';
const user = ref({
name: 'John',
profile: { age: 30, city: 'Taipei' },
});
const items = ref([1, 2, 3]);
// immediate: Π²ΡΠΏΠΎΠ»Π½ΠΈΡΡ ΡΡΠ°Π·Ρ
watch(
() => user.value.name,
(newName, oldName) => {
console.log(`ΠΠΌΡ ΠΈΠ·ΠΌΠ΅Π½ΠΈΠ»ΠΎΡΡ Ρ ${oldName} Π½Π° ${newName}`);
},
{ immediate: true }
);
// deep: ΠΎΡΡΠ»Π΅ΠΆΠΈΠ²Π°ΡΡ Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΠ΅ ΠΌΡΡΠ°ΡΠΈΠΈ
watch(
user,
(newUser) => {
console.log('Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ user ΠΈΠ·ΠΌΠ΅Π½ΡΠ½', newUser);
},
{ deep: true }
);
// flush: ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ ΡΠ°ΠΉΠΌΠΈΠ½Π³ΠΎΠΌ (pre/post/sync)
watch(
items,
() => {
console.log('items ΠΈΠ·ΠΌΠ΅Π½ΠΈΠ»ΡΡ');
},
{ flush: 'post' }
);
</script>
ΠΠ°Π±Π»ΡΠ΄Π΅Π½ΠΈΠ΅ Π·Π° Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΠΌΠΈ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠ°ΠΌΠΈβ
<script setup>
import { ref, watch } from 'vue';
const firstName = ref('John');
const lastName = ref('Doe');
watch([firstName, lastName], ([newFirst, newLast], [oldFirst, oldLast]) => {
console.log(`ΠΠΌΡ ΠΈΠ·ΠΌΠ΅Π½ΠΈΠ»ΠΎΡΡ Ρ ${oldFirst} ${oldLast} Π½Π° ${newFirst} ${newLast}`);
});
</script>
computed vs watchβ
| Π₯Π°ΡΠ°ΠΊΡΠ΅ΡΠΈΡΡΠΈΠΊΠ° | computed | watch |
|---|---|---|
| ΠΡΠ½ΠΎΠ²Π½Π°Ρ ΡΠ΅Π»Ρ | ΠΡΡΠΈΡΠ»Π΅Π½ΠΈΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ | ΠΠΎΠ±ΠΎΡΠ½ΡΠΉ ΡΡΡΠ΅ΠΊΡ ΠΏΡΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ |
| ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ | ΠΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ | ΠΠ΅ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ/Π½Π΅Ρ |
| ΠΠ΅Ρ | ΠΠ° | ΠΠ΅Ρ |
| ΠΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ | ΠΠ²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ΅ | Π―Π²Π½ΡΠΉ ΠΈΡΡΠΎΡΠ½ΠΈΠΊ |
| ΠΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΠ΅ ΠΏΠΎΠ±ΠΎΡΠ½ΡΠ΅ ΡΡΡΠ΅ΠΊΡΡ | ΠΠ΅Ρ | ΠΠ° |
| Π‘ΡΠ°ΡΠΎΠ΅/Π½ΠΎΠ²ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ | ΠΠ΅Ρ | ΠΠ° |
| ΠΡΡΠΌΠΎΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ Π² ΡΠ°Π±Π»ΠΎΠ½Π΅ | ΠΠ° | ΠΠ΅Ρ |
ΠΡΠ°Π²ΠΈΠ»ΠΎβ
computedΠ²ΡΡΠΈΡΠ»ΡΠ΅Ρ Π΄Π°Π½Π½ΡΠ΅watchΠ²ΡΠΏΠΎΠ»Π½ΡΠ΅Ρ Π΄Π΅ΠΉΡΡΠ²ΠΈΡ
ΠΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎΠ΅/Π½Π΅ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎΠ΅ ΡΡΠ°Π²Π½Π΅Π½ΠΈΠ΅β
ΠΠ΅ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎβ
<script setup>
import { ref, watch } from 'vue';
const firstName = ref('John');
const lastName = ref('Doe');
const fullName = ref('');
watch(firstName, (newFirst) => {
fullName.value = `${newFirst} ${lastName.value}`;
});
watch(lastName, (newLast) => {
fullName.value = `${firstName.value} ${newLast}`;
});
</script>
ΠΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎβ
<script setup>
import { ref, computed } from 'vue';
const firstName = ref('John');
const lastName = ref('Doe');
const fullName = computed(() => `${firstName.value} ${lastName.value}`);
</script>
ΠΡΠ°ΠΊΡΠΈΠΊΠ°: Π²ΡΡΠΈΡΠ»ΠΈΡΡ x * yβ
ΠΠ°Π½ΠΎ x = 0, y = 5, ΠΊΠ½ΠΎΠΏΠΊΠ° ΡΠ²Π΅Π»ΠΈΡΠΈΠ²Π°Π΅Ρ x Π½Π° 1 ΠΏΡΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅.
Π Π΅ΡΠ΅Π½ΠΈΠ΅ A: computed (ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΡΡΡ)β
<template>
<div>
<p>X: {{ x }}, Y: {{ y }}</p>
<p>Π Π΅Π·ΡΠ»ΡΡΠ°Ρ (X * Y): {{ result }}</p>
<button @click="x++">Π£Π²Π΅Π»ΠΈΡΠΈΡΡ X</button>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const x = ref(0);
const y = ref(5);
const result = computed(() => x.value * y.value);
</script>
Π Π΅ΡΠ΅Π½ΠΈΠ΅ B: watch (ΡΠ°Π±ΠΎΡΠ°Π΅Ρ, Π½ΠΎ Π±ΠΎΠ»Π΅Π΅ ΠΌΠ½ΠΎΠ³ΠΎΡΠ»ΠΎΠ²Π½ΠΎ)β
<script setup>
import { ref, watch } from 'vue';
const x = ref(0);
const y = ref(5);
const result = ref(0);
watch(
[x, y],
([newX, newY]) => {
result.value = newX * newY;
},
{ immediate: true }
);
</script>