watch
하나 이상의 반응형 데이터 소스를 감시하고, 소스가 변경되면 콜백 함수를 호출한다.
watch()는 기본적으로 게으르기(lazy) 때문에, 감시된 소스가 변경되었을 때만 콜백이 호출된다.
첫 번째 인자 → 감시될 소스
- 값을 반환하는 getter 함수
- ref
- 반응형 객체
- 또는 위에 나열한 것들의 배열
- ※ 반응형 객체의 속성(number, string 등)은 감시할 수 없다.
두 번째 인자 → 콜백
- 콜백의 인자
- 변경된 값
- 이전 값
- 사이드 이펙트 클린업 콜백을 등록하기 위한 함수
세 번째 인자(optional) → 옵션 객체
- immediate: 감시자가 생성되는 즉시 콜백 호출
- deep: 소스가 객체인 경우, 깊은 변경사항에서도 콜백 실행
- flush: 콜백 발생 타이밍 조정
- onTrack/onTrigger : 감시자의 의존성 디버깅
- once: 콜백을 한 번만 실행 (3.4+)
예시
const count = ref(0)
watch(count, (count, prevCount) => {
/* ... */
})
watch 첫 번째 인자로 ref 변수 사용할 때 .value 사용 여부
Vue 3에서 watch 함수의 첫 번째 파라미터로 ref 변수를 사용할 때 .value를 붙이지 않는 이유는 watch 함수가 자동으로 ref 를 자동으로 처리해주기 때문이다.
ref 자체를 watch의 첫 번째 인자로 넘기면, Vue는 내부적으로 .value 속성을 추적하여 변화가 발생할 때 콜백을 실행한다.
.value를 명시적으로 넘기면 반응형 데이터가 아닌 단순 값이 전달되므로, watch가 감시하지 못한다.
const count = ref(0)
watch(count.value, (count, prevCount) => {
/* 감시 못함 */
})
BUT
근데 실습을 하다 보니까 이는 원시 값에만 해당되는 것 같다.
const count = ref(0)
const obj = ref({
count: 0,
})
const plusCount = () => {
count.value += 1
obj.value.count += 1
}
watch(count, (newVal, oldVal) => {
console.log('count', newVal, oldVal)
})
watch(obj, (newVal, oldVal) => {
console.log('obj', newVal, oldVal)
})
두 변수 모두 변화가 있었지만, console에 찍히는(watch가 감시하는) 변수는 원시값인 count 뿐이다.
그 이유는 watch 문이 객체 자체의 참조가 바뀔 때만 감시하기 때문이다.
watch로 객체를 감시하는 방법
1. 깊은 감시
세 번째 인수로 { deep: true } 옵션을 명시적으로 사용하면 객체 내부의 모든 속성에 대해 재귀적으로 감시가 이루어진다.
watch(
obj,
(newVal, oldVal) => {
console.log('obj', newVal, oldVal)
},
{ deep: true },
)
대신 newVal과 oldVal은 모두 같은 객체를 바라보므로 콜백의 newVal과 oldVal은 동일한 값을 반환한다.
그러나 깊은 감시는 객체의 모든 중첩된 속성을 순회하기 때문에, 대규모 데이터 구조에서 사용할 경우 성능에 악영향을 미칠 수 있으므로 주의해서 사용해야 한다.
2. .value 사용
또는 obj.value를 watch의 첫 번째 인자로 사용하면 watch로 감지할 수 있다.
watch(obj.value, (newVal, oldVal) => {
console.log('obj', newVal, oldVal)
})
그 이유는 ref로 감싼 객체의 경우 reactive로 내부 깊숙이 반응하게 되기 때문이다.
isRef(obj) // true
isRef(obj.value) // false
isReactive(obj.value) // true
이는 객체에만 해당하고 원시 값에는 해당하지 않는다.
isRef(count) // true
isReactive(count.value) // false
3. 특정 속성 감시 → getter
특정 속성만 감시하려고 한다면 getter로 보내는 방법도 있다.
watch(
() => obj.value.count,
(newVal, oldVal) => {
console.log('obj', newVal, oldVal)
},
)
4. reactive()
처음부터 객체를 reactive()로 선언하게 되면 객체 자체가 반응형이 되어 watch로 감시할 수 있다.
const state = reactive({
count: 0,
})
watch(state, (newVal) => console.log(newVal))
'Vue' 카테고리의 다른 글
[ Vue ] 조건부 렌더링에 사용되는 v-if와 v-show (0) | 2024.10.15 |
---|---|
[ Vue ] reactive (0) | 2024.10.07 |
[ Vue ] ref & shallowRef (사용 이유 | 차이점 | nextTick) (0) | 2024.10.01 |
[ Vue ] React와 Vue의 반응성 시스템의 공통점/차이점 (0) | 2024.09.30 |
[ Vue ] Vue 3의 반응성 시스템 (proxy 기반 자동 반응성) (0) | 2024.09.29 |