개발을 진행하면서 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를 넣어서 안의 모든 프로퍼티를 감지할 수 있는 것이다.