๐ source๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์ฝ๋ฐฑํจ์๋ฅผ ์คํํ๋ค.
watch(source, (newValue, oldValue) => {
........
});
1๏ธโฃย ์ฒซ๋ฒ์งธ ์ธ์ : ๊ฐ์ํ๋ ค๋ ์์ค
โ ref- ref๋ฅผ ์ฌ์ฉํ๋ ๋ฐ์ํ ๋ฐ์ดํฐ
โก reactive- reactive์ getterํจ์๋ฅผ ์ฌ์ฉํ๋ ๋ฐ์ํ ๊ฐ์ฒด์ ์์ฑ
โข ๋ค์ค ์์ค
2๏ธโฃย ๋๋ฒ์งธ ์ธ์ : ์ฝ๋ฐฑํจ์๋ก ๊ฐ์ํ๋ ค๋ source๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์คํ
โ ์ฝ๋ฐฑํจ์์ ์ฒซ๋ฒ์งธ ์ธ์: ๋ณ๊ฒฝ ์ดํ์ ๊ฐ
โก ์ฝ๋ฐฑํจ์์ ๋๋ฒ์งธ ์ธ์: ๋ณ๊ฒฝ ์ด์ ์ ๊ฐ
โข ์ฝ๋ฐฑํจ์์ ์ธ๋ฒ์งธ ์ธ์(์ ํ์ฌํญ): onInvalidate,ย ํ์ํ ๋ ์์ ์ ์ ๋ฆฌํ๊ฑฐ๋ ์ทจ์ํ๋ ๋ฑ ๋ถ์์ฉ์ ๊ด๋ฆฌ
{ deep: true }
์ต์
์ด ํ์<script setup>
import { ref, watch } from 'vue';
const counter = ref(0);
const smile = ref('๐');
watch(counter, (newCount, oldCount) => {
console.log(`Counter: ${counter.value} (from ${oldCount} to ${newCount} ${smile.value})`);
});
</script>
<template>
<div>
<h1>Counter: {{ counter }}</h1>
<button @click="counter++">Increment</button>
</div>
</template>
ref๋ ๋ฐ์์ฑ์ ๊ฐ์ง ์ํ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ ๋, ๋ฐ์ ๊ฐ์ฒด ๋ฐ์ดํฐ๋ฅผ ๋ํํ๊ธฐ ๋๋ฌธ์ ์ค์ ๋ฐ์ดํฐ์ ์ ๊ทผํ๋ ค๋ฉด .value
์์ฑ์ ์ฌ์ฉํด์ผ ํ๋ค.
๊ทธ๋ฌ๋ watch ํจ์์ ๋๋ฒ์งธ ์ธ์์ธ ์ฝ๋ฐฑํจ์์ newValue, oldValue๋ ๊ฐ์ฒด๊ฐ ์๋ ref.value
์ ํด๋นํ๋ ๊ฐ์ด๋ค. ๊ทธ๋์ ๊ฐ์๋์์ด Ref๋ฅผ ์ด์ฉํด์ ๋ง๋ ๋ฐ์์ฑ์ ๊ฐ์ง ๋ฐ์ดํฐ ๊ฐ์ฒด๋ผ๋ newValue, oldValue๋ .value
์์ฑ์ ์ฌ์ฉํ์ง ์๋๋ค.
const cart = reactive({
item: 'Pencil',
count: 0
});
โย cart์ count๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ๊ฐ์ํ๊ณ ์ถ๋ค๋ฉด watch์ ์ฒซ๋ฒ์งธ ์ธ์๋ก ๋ฌด์์ ์ฌ์ฉํด์ผ ํ ๊น?
reactive๋ก ๋ง๋ ๋ฐ์ํ ๊ฐ์ฒด์ ํน์ ์์ฑ์ ๋ณ๊ฒฝ์ฌํญ์ ๊ฐ์ํ๋ ค๋ฉด watch์ ์ฒซ๋ฒ์งธ์ธ์๋ก getter
ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด๋๋ค. getterํจ์๋ฅผ ์ฐ๋ฉด (selector์ฒ๋ผ) ์ํ๋ ์์ฑ์ ๋ณ๊ฒฝ์ฌํญ๋ง ๊ฐ์งํด์ ์ฝ๋ฐฑํจ์๋ฅผ ์คํํ ์ ์๋ค.
import { reactive, watch } from 'vue';
const cart = reactive({
item: 'Pencil',
count: 0
});
watch(**() => cart.count**, (newCount, oldCount) => {
console.log(`Total Item: ${cart.count} (from ${oldCount} to ${newCount})`);
});
</script>
<template>
<div>
<p>Item: {{ cart.item }}</p>
<p>Count: {{ cart.count }}</p>
<button @click="cart.count++">Increase</button>
</div>
</template>
watch๊ฐ cart.count
์ ๋ณ๊ฒฝ์ฌํญ์ ๊ฐ์งํ๊ฒ ๋๋ฉด, count
์ ๋ณ๊ฒฝ์ , ํ ๊ฐ์ ์ฝ๋ฐฑํจ์์ ์ ๋ฌํด์ค๋ค.
(count๋ reactive๊ฐ์ฒด์ ์์ฑ์ด๋ฏ๋ก value๊ฐ ์๋ค.
watch ๋ด๋ถ์์ cart.count, oldCount, newCount๋ฑ ์ฌ๋ฌ๊ฐ์ ๋ณ์๋ฅผ ํ์ฉํ ์ ์์ผ๋ฏ๋ก value๋ผ๋ ์ด๋ฆ๋ณด๋ค๋
old**Count
์ฒ๋ผ ๋ช ํํ ๋ค์ด๋ฐํ๋๊ฒ ์ค์ํ๋ค๋ ์๊ฐ์ด ๋ ๋ค!**
์ฌ๋ฌ๊ฐ์ ๊ฐ์ ๊ฐ์ํ๋ค๊ฐ ํ๋์ ํธ๋ค๋ฌ๋ฅผ ์คํํ๊ณ ์ถ์ ๋
watch
ํจ์์ ์ธ์๋ก ์ฌ๋ฌ๊ฐ์ ๊ฐ์ ์ค๋๋ ๋ฐฐ์ด๋ก ๊ฐ์ผ๋ค.
<script setup>
import { ref, reactive, watch } from 'vue';
const temperature = ref(25);
const humidity = ref(50);
const finedust = reactive({
quality: 'Good'
});
watch(
[temperature, humidity, () => finedust.quality],
([newTemperature, newHumidity, newFinedust], [oldTemperature, oldHumidity, oldFinedust]) => {
console.log(`Temperature: ${temperature.value} (from ${oldTemperature}ยฐC to ${newTemperature}ยฐC)`);
console.log(`Humidity: ${humidity.value} (from ${oldHumidity}% to ${newHumidity}%)`);
console.log(`finedust: ${finedust.quality} (from ${oldFinedust} to ${newFinedust})`);
}
);
function showYesterday(temp, humid, quality) {
temperature.value += temp;
humidity.value += humid;
finedust.quality = quality;
}
</script>
<template>
<div>
<h1>Weather</h1>
<p>Temperature: {{ temperature }}ยฐC</p>
<p>Humidity: {{ humidity }}%</p>
<p> Quality: {{ finedust.quality }}</p>
<button @click="showYesterday(3, 5, 'Bad')">Show Yesterday</button>
</div>
</template>
source
์จ๋์ ์ต๋๋ ref๋ก ๊ด๋ฆฌํ๊ณ ๋ฏธ์ธ๋จผ์ง๋ reactive๋ก ๊ด๋ฆฌํ๊ณ ์๋ค.
watchํจ์์ ์ฒซ๋ฒ์งธ ์ธ์์๋ source๊ฐ์ ๋ฐฐ์ด๋ก ๋ฌถ์ด์ ๋ฃ์์ ์๊ณ , reactive ๋ฐ์์ฑ ๊ฐ์ฒด๋ getterํจ์๋ก ์ํ๋ ๊ฐ๋ ํน์ ํ์ฌ ๋ฃ๋๋ค.
watch(
[temperature, humidity, () => finedust.quality]
์ฝ๋ฐฑํจ์
์ฝ๋ฐฑํจ์์ ๊ฐ ์ธ์์๋ ๊ฐ source๋ค์ ๋ณ๊ฒฝ์ , ํ ๊ฐ๋ค์ ๋ฐฐ์ด๋ก ๋ฌถ์ด์ ๋ฃ๋๋ค.
([newTemperature, newHumidity, newFinedust],
[oldTemperature, oldHumidity, oldFinedust]) => { ... }
๐ก ์ง์ ํ ์์ฑ์ ์์ฑ๊ฐ๋ ๊ฐ์ํ๋ค.
๋ฐ์ํ ๊ฐ์ฒด๋ฅผ ์ง์ watchํ๋ฉด ์์์ ์ผ๋ก ๊น์ ๊ฐ์์๊ฐ ์์ฑ๋๋ค.
์ฆ, ์์ฑ ๋ฟ ์๋๋ผ ์ค์ฒฉ๋ ์์ฑ์๋ ํธ๋ฆฌ๊ฑฐ๋๋ค.
const person = reactive({
name: 'ํ๊ธธ๋',
age: 30,
hobby: '์ด๋',
obj: {
count: 0,
},
});
obj
์ ๊ฐ์ ๋๊ธธ ๊ฒฝ์ฐ obj
์ ๊ฐ์ด ๋ฐ๋๊ฒฝ์ฐ์๋ง ํธ๋ฆฌ๊ฑฐ๋๋ค.watch(
() => person.obj,
(newValue) => {
// ๊ฐ์ฒด์ ๊ฐ์ด ๋ฐ๋ ๊ฒฝ์ฐ์๋ง ํธ๋ฆฌ๊ฑฐ ๋๋ค.
}
);
deep
์ต์
์ ์ฌ์ฉํ๋ฉด ๊น์ ๊ฐ์์๋ก ๊ฐ์ ํ ์ ์๋ค.watch(
() => person.obj,
(newValue) => {
console.log('newValue: ', newValue);
},
{ deep: true } //๋ง์ง๋ง ๋งค๊ฐ๋ณ์
);
๐จย deep ์ต์ ์ ํฐ ๋ฐ์ดํฐ ๊ตฌ์กฐ์์ ์ฌ์ฉ์ ๋น์ฉ์ด ๋ง์ด ๋ค ์ ์์ผ๋ฏ๋ก, ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ ์ฑ๋ฅ ์ํฅ์ ์ฃผ์ํ์.
๐ก ์ต์ด์ ์ฆ์ ์คํ๋๋๋กํ๋ ์ต์
watch
๋ ๋ฐ์ํ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ํ๋ค๊ฐ, ๋ฐ์ํ ๋ฐ์ดํฐ์ โ๋ณํโ๊ฐ ์ผ์ด๋ฌ์ ๋ ์ต์ด๋ก ์คํ๋๋ค.
immediate
์ต์
์ ์ฌ์ฉํ๋ฉด ์ต์ด์ ํ์ด์ง๋ฅผ ์ฝ์์ ๋ ์ฆ์์คํ๋๋๋ก ํ ์ ์๋ค.
watch(
() => person.obj,
(newObj) => {
console.log('newCount: ', newObj.count);
},
{ immediate: true },
);
computed()
๋ ๊ฒฐ๊ณผ๊ฐ์ ๋ฐํํ์ง๋ง, watch()
๋๋ฐ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ์ ๋ ํน์ ๋์์ ์คํ
computed
โ vue ์ธ์คํด์ค์ ์ํ(ref, reactive ๋ณ์)์ ์ข
์๊ด๊ณ๋ฅผ ์ธํ
ํ ๋.
ex) ย reverseMessage
๋ย message
ย ๊ฐ์ ๋ฐ๋ผ ๊ฒฐ์ ๋์ด์ง๋ ์ข
์๊ด๊ณ์ ์๋ค
watch
โ vue ์ธ์คํด์ค์ ์ํ(ref, reactive ๋ณ์)๋ณ๊ฒฝ์์ ์ ํน์ Action( api ํธ์ถ, route push ๋ฑ)์ ์ทจํ ๋
1๏ธโฃย ์ปดํฌ๋ํธ๊ฐ ์์ฑ๋ ๋, 2๏ธโฃ์ฝ๋ฐฑํจ์ ๋ด๋ถ์ ๋ฐ์์ฑ ๋ฐ์ดํฐ์ ๋ณํ๊ฐ ๊ฐ์ง๋ ๋, ์๋์ผ๋ก ์คํํ๋ค.
const message = ref('');
watchEffect(()=> {
console.log(message.value);
})
message
ย ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์ฝ์์ด ์ถ๋ ฅ๋๋ค.
์ฝ๋ฐฑ ํจ์ ์์ ๋ฐ์ํ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์๋์ผ๋ก ๊ฐ์งํ์ฌ ์คํ
์ฌ์ฉ์์
โ๏ธย ์๋์ ์ฅ ๊ธฐ๋ฅ์ ๋ง๋ค๋
save()
ย ๋ก ์ ์ฅํจ์๋ฅผ ๋ง๋ค์ด ๋๊ณ , ์ด์ ๊ฐ์ด watchEffect๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
const message = ref('');
watchEffect(()=> {
save(message.value);
})
์์ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ฑํ๋ฉด, ๋ด์ฉ์ด ์์ ๋ ๋๋ง๋ค ์๋์ผ๋ก ์ ์ฅํจ์ย save()
๊ฐ ์คํ๋๋ค.
TIP!ย ๋ฐ์ธ๋ฉ๋v-model
์ย .lazy
ย ์ต์
์ ์ค๋ค๋ฉด ํฌ์ปค์ค๊ฐ ์ด๋๋์์๋ ์ ์ฅํ๋ ๋ฐฉ์์ผ๋ก๋ ๋ณ๊ฒฝํ ์ ์์ ๊ฒ์ด๋ค.