개발을 진행하면서 watch
를 사용하는 분들이 계셨는데, 데이터를 어떻게 넣느냐에 따라 감지가 되는지 안되는지 확인하다보니 궁금증이 생겨서 찾아보고 그에 대한 글을 작성해보고자 한다
import { ref, watch } from 'vue';
const count = ref(0);
watch(count, (newValue, oldValue) => {
console.log(`count changed from ${oldValue} to ${newValue}`);
});
count 변화를 감시하며 newValue, oldValue를 통해 변화를 추적한다
const count = ref(0);
watch(count, (newValue, oldValue) => {
console.log(`count changed from ${oldValue} to ${newValue}`);
});
count.value = 1; // 감지됨
.value
를 전달하지 않고 count
만 넣어도 vue 내부에서 처리를 한다. 참조 값
이 변했기 때문에 이를 감지한다.ref
로 감싼 경우const user = ref({ name: 'Alice', age: 25 });
watch(user, (newValue, oldValue) => {
console.log('user object changed');
});
user.value.name = 'Bob'; // 감지되지 않음
user.value = { name: 'Bob', age: 25 }; // 감지됨
user
를 하면 ref로 감싸진 참조가 변경되지는 않았기 때문에 감지를 하지 못한다. 참조값
을 감지하기 때문이다.deep
속성에 true를 주면되긴 하지만 건너뛰어가본다.(1) 원시 타입
새롭게
값이 할당된다.(2) 객체 타입
참조 자체
를 변경하면 새로운 메모리 공간에 할당되고, 내부 속성 등이 바뀌면 메모리 주소가 바뀌지 않는다. user.value
는 객체 자체이다. 이를 Proxy
로 감싼다.
근데 ref
를 하면 안에 vue 내부에서 RefImpl이라는 객체를 활용한다고 알고 있다.
근데 왜 객체에서 reactive로 감싸서 Proxy객체로 바꿔지는걸까?
Vue가 내부 속성의 변경을 Proxy를 통해 자동으로 감싸서 변화를 감지해준다.
const user = ref({ name: 'Alice', age: 25 });
// 객체 내부 속성의 변화를 감지할 수 있음 (deep 옵션 없이도 가능)
watch(user.value, (newValue, oldValue) => {
console.log('user object changed');
});
user.value.name = 'Bob'; // 감지됨
Vue3는 ref를 생성할 때 RefImpl
클래스 인스턴스를 반환하여 .value
프로퍼티를 통해 값이나 객체에 접근할 수 있다.
원시 값의 경우 .value
를 통해 해당 값을 반응형으로 만든다
객체의 경우 ref로 감싸도 reactive로 감싸서 Proxy로 변환을 해준다.
Proxy의 경우에는 get, set트랩이 있는데, 속성 접근 및 변경을 추적해주는 역할을 해준다.
그래서 위의 예시처럼 객체 내부 속성의 변화
도 감지할 수 있게 되어 첫 번째 인자에 user.value를 넣어서 안의 모든 프로퍼티를 감지할 수 있는 것이다.