Watch
ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ํ ์ํ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ํน์ ์์
์ ์ํํ ์ ์๋ค.<template>
<div></div>
</template>
<script>
import { ref, watch } from "vue";
export default {
setup() {
const message = ref("");
//๋ฐ์ํ(message)๋ฅผ ๊ฐ์งํ๊ณ
//์ฝ๋ฐฑํจ์๋ฅผ ๋๊ฒจ์ฃผ๋๋ฐ ๋ณํ๊ฐ ์๊ฒผ์ ๋์ ๋ฐ์ดํฐ(newValue)
//๊ธฐ์กด๊ฐ(oldValue)
watch(message, (newValue, oldValue) => {
console.log("newValue", newValue);
console.log("oldValue", oldValue);
});
return { message };
},
};
</script>
<style lang="scss" scoped></style>
์ด๋ ๊ฒ ๊ฐ(Hello)๋ก ์์ ํ๊ฒ๋๋ฉด
oldValue
์ ๊ฐ์ ์ฒ์์ ๋น๊ฐ('')์ ๋ฃ์๊ณ newValue
์ ๊ฐ์๋ 'Hello'๋ฅผ ๋ฃ์๊ธฐ ๋๋ฌธ์ ๋ณํ๊ฐ ์๊ธด ๊ฐ์๋ 'Hello'๊ฐ ๋ค์ด๊ฐ๊ฒ ๋๋ค. ๋ ๋ค์ ์์ ํด๋ณด์.
'Hello'์์ 'Hello ChaeWon'์ผ๋ก ์์ ํ์๋ค.
๊ธฐ์กด์ ์์ ๋ ๊ฐ 'Hello'๊ฐ ๊ธฐ์กด๊ฐ์ด ๋๋ฉด์ 'Hello ChaeWon'์ด ์๋ก์ด ๊ฐ์ผ๋ก ๋ค์ด๊ฐ๊ฒ ๋๋ค.
ref
, reactive
, computed
, getter ํจ์
, array
ํ์
์ด ๋ ์ ์๋ค.<template>
<div></div>
</template>
<script>
import { ref, watch } from "vue";
export default {
setup() {
const x = ref(0);
const y = ref(0);
//watch์ ์ฒซ ๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ก getter๋ฅผ ์ฌ์ฉํ์ฌ ๋ ์์ ํฉ์ ๊ฐ์งํ ์ ์๋ค.
watch(
() => x.value + y.value,
sum => {
console.log("sum: ", sum);
},
);
return { x, y };
},
};
</script>
<style lang="scss" scoped></style>
์ด๊ธฐ๊ฐ x์ 1์ ์ฌ๋ ค๋ณด์
๋ณ๊ฒฝ๋ ๊ฐ์ ํ์ธ ํ ์ ์๋ค. ์ด๋ ๊ฒ sum์ ๊ณ์ํด์ ๋ณํํ๋ ์๋ก์ด ๊ฐ์ ํ์ธํ ์ ์๋ค. ์๋์ ๊ฐ์ด ๊ธฐ์กด๊ฐ ๋ํ ์ถ๋ ฅํ ์ ์๋ค.
<template>
<div></div>
</template>
<script>
import { ref, watch } from "vue";
export default {
setup() {
const x = ref(0);
const y = ref(0);
//watch์ ์ฒซ ๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ก getter๋ฅผ ์ฌ์ฉํ์ฌ ๋ ์์ ํฉ์ ๊ฐ์งํ ์ ์๋ค.
watch(
() => x.value + y.value,
(sum, oldValue) => {
console.log("sum: ", sum);
console.log("oldValue: ", oldValue);
},
);
return { x, y };
},
};
</script>
<style lang="scss" scoped></style>
<template>
<div></div>
</template>
<script>
import { ref, watch } from "vue";
export default {
setup() {
const x = ref(0);
const y = ref(0);
//Array
//์ด๋ ๊ฒ ๋ฐฐ์ด๋ก ๊ฐ์ ๋ฃ์ผ๋ฉด ๋ฐ๋ ๊ฐ ๋ํ ๋ฐฐ์ด๋ก ๋ฐ๋๋ค.
watch([x, y], ([newX, newY]) => {
console.log(newX, newY);
});
return { x, y };
},
};
</script>
<style lang="scss" scoped></style>
<template>
<div></div>
</template>
<script>
import { ref, watch } from "vue";
export default {
setup() {
const x = ref(0);
const y = ref(0);
const obj = reactive({
count: 0,
});
//object
watch(obj, (newObj, oldObj) => {
console.log("newObj: ", newObj);
});
return { x, y, obj };
},
};
</script>
<style lang="scss" scoped></style>
์ด๋ ๊ฒ count๋ฅผ 1๋๋ฆฌ๋ฉด count๊ฐ 1์ฆ๊ฐํ ๊ฑธ ํ์ธํ ์ ์๋ค. ๋ง์ฝ object์์ ์์ฑ ํ๋๋ง ๊ฐ์งํ๊ณ ์ถ์ ๋ ์ด๋ป๊ฒ ํด์ผ๋ ๊น?
<template>
<div></div>
</template>
<script>
import { ref, watch } from "vue";
export default {
setup() {
const x = ref(0);
const y = ref(0);
const obj = reactive({
count: 0,
});
//object
//nember๋ก ํ์ธ์ด ๋๋ค.
console.log(typeOf obj.count);
watch(obj.count, (newObj, oldObj) => {
console.log("newObj: ", newObj);
});
return { x, y, obj };
},
};
</script>
<style lang="scss" scoped></style>
obj.count
๋ก ํ๋ค๋ฉด ์ด๋ป๊ฒ ๋ ๊น? ์๋๋ค. ์ด์ ๋ number
์ด๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๋ ๊ฒ ํน์ object์ ์์ฑ์ ๊ฐ์งํ๊ณ ์ถ์ผ๋ฉด๋ getter ํจ์
๋ฅผ๋ก ๋ฃ์ด์ค๋ค
<template>
<div></div>
</template>
<script>
import { ref, watch } from "vue";
export default {
setup() {
const obj = reactive({
count: 0,
});
//object
watch(
() => obj.count,
(newObj, oldObj) => {
console.log("newObj: ", newObj);
},
);
return { obj };
},
};
</script>
<style lang="scss" scoped></style>
๊ทธ๋ผ ์ด๋ ๊ฒ 1์ด ์ฐํ๋ ๊ฑธ ํ์ธํ ์ ์๋ค. ๋ํ object ํ์
์ ๊ฐ์งํ ๋๋ newObj
์ oldObj
๋ฅผ ๊ฐ์ด ๊ฐ์งํ๋ค.
<template>
<div></div>
</template>
<script>
import { ref, watch } from "vue";
export default {
setup() {
const obj = reactive({
count: 0,
});
//object
watch(obj, (newObj, oldObj) => {
console.log("newObj: ", newObj);
console.log("oldObj: ", oldObj);
});
return { obj };
},
};
</script>
<style lang="scss" scoped></style>
๊ทธ๋ฆฌ๊ณ ๋ฐ์ํ ๊ฐ์ฒด๋ฅผ ์ง์ watch()
ํ๋ฉด ์์์ ์ผ๋ก ๊น์ ๊ฐ์์๊ฐ ์์ฑ๋๋ค. ์ฆ, ์์ฑ ๋ฟ๋ง์๋๋ผ ๋ชจ๋ ์ค์ฒฉ๋ ์์ฑ์๋ ํธ๋ฆฌ๊ฑฐ๊ฐ ๋๋ค.
<template>
<div></div>
</template>
<script>
import { ref, watch } from "vue";
export default {
setup() {
const person = reactive({
name: "์ด์ฑ์",
age: "33",
hobby: "์ด๋",
obj: {
count: 0,
},
});
watch(person, newValue => {
console.log("newValue: ", newValue);
});
return { person };
},
};
</script>
<style lang="scss" scoped></style>
์ด๋ ๊ฒ ๋ณ๊ฒฝ์ํด๋ ๋ฅํ๊ฒ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ ๊ฑธ ๋ณผ ์ ์๋ค. ๊ฐ์ฒด์์ ๊ฐ์ฒด๊น์ง, ๋ง์ฝ getter ํจ์๋ก obj
๋ฅผ ๋๊ธฐ๋ฉด ์ด๋ป๊ฒ ๋ ๊น? obj
์์ฒด๊ฐ ๋ณ๊ฒฝ ๋์์ ๋๋ง ๊ฐ์ง๊ฐ๋๋ค. ๊ฐ์ฒด ์์ ๊ฐ์ฒด์ ๊ฐ์ด ๋ณํ์ ๋๊ฐ ์๋๋ผ obj
์ ์์ฑ ๊ฐ์ด ๋ณ๊ฒฝ ๋์์ ๋๋ง ๊ฐ์ง๊ฐ ๋๋ค. getter ํจ์๋ก ๋ฐ์ ๊ฐ์ด ๋ฐ๊ผ๋ ์ ๋ฐ๊ผ๋๋ฅผ ๊ฐ์ง๊ณ ์ฒดํฌํ๋ค.
์ด๋ ๊ฒ watch
๋ ๋ฐ์ํ ์ํ๊ฐ ๋ณ๊ฒฝ ๋์์ ๋ ๊ฐ์งํ์ฌ callback ํจ์๋ฅผ ์คํ์์ผ์ค๋ค. ์ด๋ฌํ callback ํจ์๋ฅผ ์์ ์ฆ์ ์คํํ๊ณ ์ถ์ ๋๊ฐ ์๋ค. ์ด๋ด ๋ immediate
๊ฐ ์๋ค.
<template>
<div>
<p>{{ message }}</p>
<p>{{ reverseMessage }}</p>
</div>
</template>
<script>
import { ref, watch } from "vue";
export default {
setup() {
const message = ref("hello vue3");
const reverseMessage = ref("");
watch(
message,
newValue => {
//split๋ก ์ชผ๊ฐ๊ณ reverse๋ก ๋ฐ์ ํ join์ผ๋ก ๋ถ์ฌ์ค๋ค. ๊ทธ๋ฆฌ๊ณ reverseMessage๋ก ๋ฃ์ด์ค๋ค.
reverseMessage.value = newValue.split("").reverse().join("");
}
);
return { message, reverseMessage };
},
};
</script>
์ด๋ ๊ฒ ๋์ ๋ ์ต์ด๋ก message
๊ฐ ์์ ์ด ๋ ํ reversMessge
๊ฐ ๊ฐ์ง๋๋ค.
์ต์ด๋ก ๋ฐ๋ก ์คํํ๊ธฐ ์ํด์๋
<template>
<div>
<p>{{ message }}</p>
<p>{{ reverseMessage }}</p>
</div>
</template>
<script>
import { ref, watch } from "vue";
export default {
setup() {
const message = ref("hello vue3");
const reverseMessage = ref("");
watch(
message,
newValue => {
//split๋ก ์ชผ๊ฐ๊ณ reverse๋ก ๋ฐ์ ํ join์ผ๋ก ๋ถ์ฌ์ค๋ค. ๊ทธ๋ฆฌ๊ณ reverseMessage๋ก ๋ฃ์ด์ค๋ค.
reverseMessage.value = newValue.split("").reverse().join("");
},
// ์ด๋ ๊ฒ ์ฆ์ ์คํ์ ์ํ๋ฉด immediate true๋ฅผ ํ์ฉํ ์ ์๋ค.
{
immediate: true,
},
);
return { message, reverseMessage };
},
};
</script>
์ด๋ ๊ฒ ๋ฐ๋ก immediate
๋ฅผ ํตํด์ ์ฆ์ ์คํ ํ ์ ์๋ค.
<template>
<div>
<p>{{ message }}</p>
<p>{{ reverseMessage }}</p>
</div>
</template>
<script>
import { ref, watch } from "vue";
export default {
setup() {
const message = ref("hello vue3");
const reverseMessage = ref("");
watch(
message,
newValue => {
//split๋ก ์ชผ๊ฐ๊ณ reverse๋ก ๋ฐ์ ํ join์ผ๋ก ๋ถ์ฌ์ค๋ค. ๊ทธ๋ฆฌ๊ณ reverseMessage๋ก ๋ฃ์ด์ค๋ค.
reverseMessage.value = newValue.split("").reverse().join("");
},
// ์ด๋ ๊ฒ ์ฆ์ ์คํ์ ์ํ๋ฉด immediate true๋ฅผ ํ์ฉํ ์ ์๋ค.
{
immediate: true,
},
);
return { message, reverseMessage };
},
};
</script>
์๋๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด๋ค.
<template>
<div>
<p>{{ message }}</p>
<p>{{ reverseMessage }}</p>
</div>
</template>
<script>
import { ref, watch } from "vue";
export default {
setup() {
const message = ref("hello vue3");
const reverseMessage = ref("");
// 1) ์ฒซ ๋ฒ์งธ ๋ฐฉ๋ฒ
// watch(
// message,
// newValue => {
// //split๋ก ์ชผ๊ฐ๊ณ reverse๋ก ๋ฐ์ ํ join์ผ๋ก ๋ถ์ฌ์ค๋ค. ๊ทธ๋ฆฌ๊ณ reverseMessage๋ก ๋ฃ์ด์ค๋ค.
// reverseMessage.value = newValue.split("").reverse().join("");
// },
// // ์ด๋ ๊ฒ ์ฆ์ ์คํ์ ์ํ๋ฉด immediate true๋ฅผ ํ์ฉํ ์ ์๋ค.
// {
// immediate: true,
// },
// );
// 2) ๋ ๋ฒ์งธ ๋ฐฉ๋ฒ
// const reverseFunction = newValue => {
// reverseMessage.value = newValue.split("").reverse().join("");
// };
// watch(message, reverseFunction);
// //์ต์ด ์คํ์ผ ๋ watch์ newValue์ ๊ฐ์ด ์๋ค. ๊ทธ๋ ๊ธฐ์ message.value๋ฅผ ๋ฃ์ด์ค๋ค.
// reverseFunction(message.value);
// return { message, reverseMessage };
// 3) ์ธ ๋ฒ์งธ ๋ฐฉ๋ฒ
const reverseFunction = () => {
reverseMessage.value = message.value.split("").reverse().join("");
};
watch(message, reverseFunction);
reverseFunction();
return { message, reverseMessage };
},
};
</script>
computed
์ watch
๋ ๋น์ทํ ์ญํ ์ ํ๊ณ ์๋ค.
computed
- Vue ์ธ์คํด์ค์ ์ํ(ref, reactive ๋ณ์)์ ์ข ์ ๊ด๊ณ๋ฅผ ์๋์ผ๋ก ์ธํ ํ๊ณ ์ ํ ๋๋computed
๋ก ๊ตฌํํ๋ ๊ฒ์ด ์ข๋ค. ์ ์์๋ฅผ ์๋ก ๋ค์๋ฉด 'reverseMessage'๋ 'message' ๊ฐ์ ๋ฐ๋ผ ๊ฒฐ์ ๋์ด์ง๋ ์ข ์๊ด๊ณ์ ์๋ค. ์ด ์ข ์๊ด๊ณ ์ฝ๋๊ฐ ๋ณต์กํด์ง๋ฉดwatch
๋ก ๊ตฌํํ ๊ฒฝ์ฐ ๋ ๋ณต์กํด์ง๊ฑฐ๋ ์ค๋ณต๊ณ์ฐ ์ค๋ฅ๋ฅผ ๋ฐ์ ์ํฌ ์ ์๋ค.
watch
- Vue ์ธ์คํด์ค์ ์ํ(ref, reactive ๋ณ์)์ ๋ณ๊ฒฝ ์์ ์ ํน์ ์ก์ (call api, push, route ๋ฑ)์ ์ทจํ๊ณ ์ ํ ๋ ์ ํฉํ๋ค. ๋๊ฒ์ ๊ฒฝ์ฐcomputed
๋ก ๊ตฌํ ๊ฐ๋ฅํ ๊ฒ์ด๋ผ๋ฉดwatch
๊ฐ ์๋๋ผcomputed
๋ก ๊ตฌํํ๋๊ฒ ๋๋ถ๋ถ ์ณ๋ค.
WatchEffect
์ ์ฝ๋๋ ์ปดํฌ๋ํธ๊ฐ ์์ฑ๋ ๋ ์ฆ์ ์คํ๋๋ค.<template>
<div>
<form action="">
<!-- ์๋ฐฉํฅ ๋ฐ์ธ๋ฉ์ ์ํด์ v-model ์ฌ์ฉ-->
<input v-model="title" type="text" placeholder="title" />
<textarea v-model="contents" placeholder="contents"></textarea>
</form>
</div>
</template>
<script>
import { ref, watchEffect } from "vue";
export default {
setup() {
const title = ref("");
const contents = ref("");
watchEffect(() => {
console.log("watchEffect");
console.log("title: ", title.value);
console.log("contents: ", contents.value);
});
return { title, contents };
},
};
</script>
์ด๋ ๊ฒ ์ฝ๋ฐฑํจ์ ์์ ์ ์ธํ ๋ฐ์ํ ๋ฐ์ดํฐ์ ๋ณ๊ฒฝ์ด ์ผ์ด๋๋ฉด ๊ทธ๊ฒ์ ๊ฐ์งํด์ ์ถ๋ ฅ์ด ๋๋ ๊ฑธ ํ์ธ ํ ์ ์๋ค. ๋ฐ์ํ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ์ด ๋์์ ๋ ์ฝ๋ฐฑํจ์๊ฐ ํธ์ถ๋๋ ๊ฑธ ๋ณผ ์ ์๋ค.
๊ทธ๋ฆฌ๊ณ watchEffect
๋ watch
์ ๋ค๋ฅด๊ฒ ์ฒ์ ์คํ ํ์ ๋ ์ต์ด ํ๋ฒ ์ฆ์ ์คํํ๋ค.
์ ๋ฒ์ ๋ฐฐ์ด modifiers
๋ฅผ ํ์ฉํด ์์ ๋ฅผ ๋ง๋ค ์ ์๋ค.
<template>
<div>
<!-- 3) button์ ๊ธฐ๋ณธ ์์ฑ์ submit์ด๋ฉฐ button์ ํด๋ฆญ ์ form์ submit์ด ํธ์ถ๋๋ค. -->
<!-- 4) ์ ์ฅ ํ์์ ๋ submit์ ํธ์ถ๋ก ์ธํด ์๋ก๊ณ ์นจ์ด ๋ฐ์ํ๋ prevent๋ฅผ ๋ฃ์ด์ค๋ค.-->
<form @submit.prevent="save(title, contents)">
<!-- 1) ์๋ฐฉํฅ ๋ฐ์ธ๋ฉ์ ์ํด์ v-model ์ฌ์ฉ-->
<!-- 2) ๋งค๋ฒ ๊ฐ์ด ๋ณ๊ฒฝ๋๋๊ฒ ์๋ focus๊ฐ ๋จ์ด ์ก์ ๋ ๊ฐ์ด ๋ณ๊ฒฝ๋ ์ ์๋๋ก
lazy๋ฅผ ์ถ๊ฐํ๋ค.-->
<input v-model.lazy="title" type="text" placeholder="title" />
<textarea v-model.lazy="contents" placeholder="contents"></textarea>
<hr />
<!-- 5) form์ ์๋ button์ @click="save(title, contents)"๋ก๋ ๋ง๋ค ์ ์๋ค. -->
<!-- <button @click="save(title, contents)">์ ์ฅ</button> -->
<button>์ ์ฅ</button>
</form>
</div>
</template>
<script>
import { ref, watchEffect } from "vue";
export default {
setup() {
const title = ref("");
const contents = ref("");
//๊ฐ์ ์ ์ฅํ๊ธฐ ์ํ ๋ฉ์๋๋ฅผ ํ๋ ๋ง๋ค์ด์ค๋ค.
const save = (title, contents) => {
console.log(`์ ์ฅ๋์์ต๋๋ค. title:${title}, contents:${contents}`);
};
watchEffect(() => {
console.log("watchEffect");
save(title.value, contents.value);
});
return { title, contents, save };
},
};
</script>
watch
์ watchEffect
๋ ๋ค ๊ด๋ จ ์์
(api call, push, route ๋ฑ)์ ๋ฐ์์ ์ผ๋ก ์ํํ ์ ์๊ฒ ํด์ค๋ค. ํ์ง๋ง ์ฃผ์ํ ์ฐจ์ด์ ์ ๊ด๋ จ๋ ๋ฐ์ํ ๋ฐ์ดํฐ๋ฅผ ์ถ์ ํ๋ ๋ฐฉ์์ด๋ค.
watch
- ๋ช ์์ ์ผ๋ก ๊ด์ฐฐ๋ ์์ค๋ง ์ถ์ ํ๋ค. ์ฝ๋ฐฑ ๋ด์์ ์ก์ธ์คํ ํญ๋ชฉ์ ์ถ์ ํ์ง ์์ผ๋ฉฐ ๋ํ ์ฝ๋ฐฑ์ ์์ค๊ฐ ์ค์ ๋ก ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ์๋ง ํธ๋ฆฌ๊ฑฐ๋๋ค.watch
์ข ์์ฑ ์ถ์ ์ ๋ถ์์ฉ๊ณผ ๋ถ๋ฆฌํ์ฌ ์ฝ๋ฐฑ์ด ์คํ๋์ด์ผ ํ๋ ์๊ธฐ๋ฅผ ๋ณด๋ค ์ ํํ๊ฒ ์ ์ดํ ์ ์๋ค.
watchEffect
- ๋ฐ๋ฉด ์ข ์์ฑ ์ถ์ ๊ณผ ๋ถ์์ฉ์ ํ ๋จ๊ณ๋ก ๊ฒฐํฉํ๋ค. ๋๊ธฐ ์คํ ์ค์ ์ก์ธ์ค๋๋ ๋ชจ๋ ๋ฐ์ ์์ฑ์ ์๋์ผ๋ก ์ถ์ ํ๋ค. ์ด๊ฒ์ ๋ ํธ๋ฆฌํ๊ณ ์ผ๋ฐ์ ์ผ๋ก ๋ ๊ฐ๊ฒฐํ ์ฝ๋๋ฅผ ์์ฑํ์ง๋ง ์ข ์์ฑ์ ๋ ๋ช ์์ ์ผ๋ก ๋ง๋ ๋ค.