ref()
composition API에서 반응형 상태를 선언 시 권장하는 방법
import { ref } from 'vue'
const count = ref(0)
템플릿에서 ref를 사용할 때는 .value 를 추가할 필요가 없다. 편의상 ref는 템플릿 내에서 사용될 때 자동으로 언래핑된다.
이벤트 핸들러에 직접 참조를 변경할 때도 .value 가 불필요하다.
<button @click="count++">plus</button>
<p>count : {{ count }}</p>
다만 이벤트 핸들러에 따로 정의한 함수를 바인딩하여 ref를 변경할 경우, 스크립트에서 .value 는 필요하다.
<button @click="plusCount">plus</button>
<p>count : {{ count }}</p>
const plusCount = () => {
count.value++
}
🔎 react의 useState와 비슷한 기능?
상태 관리를 위한 도구라는 점에서는 유사
그러나 useState는 상태 업데이트 함수인 setState를 통해 state를 변경해야 하지만 ref는 .value를 통해 상태 값에 접근하고 변경한다.
※ setState 함수의 사용을 통해 상태의 변화를 감지하여 react가 리렌더링
※ ref 값의 변경을 vue의 반응형 시스템이 자동으로 추적 ㄷㄷ
shallowRef()
ref()의 얕은 버전
.value 의 접근만 반응형이고 내부 값의 변경은 반응형으로 동작하지 않는다.
일반적으로 대규모 데이터 구조의 성능 최적화 또는 외부 상태 관리 시스템과의 통합에 사용된다.
const state = shallowRef({ count: 1 })
// change(변경)을 트리거하지 않음 (watch 감시 X)
state.value.count = 2
// change를 트리거 함 (watch 감시 O)
state.value = { count: 2 }
watch(state, (newVal) => console.log(newVal))
Vue에서 일반 변수 대신 ref를 사용하는 이유
⭐ Vue의 반응성 시스템
- 컴포넌트가 처음 렌더링될 때, Vue는 렌더링 과정에서 사용된 모든 ref를 추적한다.
- 나중에 ref가 변경되면, 이를 추적하는 컴포넌트에 대해 재렌더링을 트리거한다.
- 표준 Javascript에서는 일반 변수의 접근이나 변형을 감지하는 방법이 없다. (getter/setter는 가능)
- .value 속성은 Vue에게 ref가 액세스되거나 변경되었을 때를 감지할 기회를 준다.
- 내부적으로, Vue는 getter에서 추적을 수행하고, setter에서 트리거를 수행한다.
- 결과적으로 템플릿에서 ref를 사용하고 나중에 ref의 값을 변경하면, Vue는 자동으로 이 변경을 감지하고 DOM을 적절하게 업데이트한다.
DOM 업데이트 타이밍
반응 상태를 변경하면 DOM이 자동으로 업데이트된다. 하지만 DOM 업데이트는 동기적으로 적용되지 않는다.
대신 Vue는 업데이트 주기의 “다음 틱”까지 버퍼링하여 얼마나 많은 상태 변경을 수행하든 각 컴포넌트가 한 번만 업데이트되도록 한다.
상태 변경 후, DOM 업데이트가 완료될 때까지 기다리려면 nextTick() 전역 API를 사용할 수 있다.
import { nextTick } from 'vue'
const plusCount = async () => {
count.value++
await nextTick()
console.log('DOM 업데이트 완료', count.value)
}
ref와 shallowRef 차이
ref와 shallowRef는 원시값에 대한 동작은 차이가 없다.
const count = ref(0)
const shallowCount = shallowRef(0)
const plusCount = () => {
count.value += 1
shallowCount.value += 1
}
그러나 shallowRef는 ref의 얕은 반응형이기 때문에 객체를 다룰 때는 차이가 발생한다.
const obj = ref({
name: 'kim',
count: 0,
})
const shallowObj = shallowRef({
name: 'lee',
count: 0,
})
ref의 경우 객체의 속성에 변경이 일어나면 <template> 에 바로 반영된다. (반응형)
그러나 shallowRef로 정의한 변수는 객체의 변경은 발생하지만 <template> 에 바로 반영되지는 않는다. (= 내부 깊숙이까지 반응형으로 동작하지 않는다.)
이때 shallowRef로 정의한 변수를 변경한 후 바로 반영하기 위해서는 triggerRef를 사용해 강제 트리거할 수 있다.
const shallowObj = shallowRef({
name: 'lee',
count: 0,
})
const plusShallowCount = () => {
shallowObj.value.count += 1
triggerRef(shallowObj)
}
'Vue' 카테고리의 다른 글
[ Vue ] reactive (0) | 2024.10.07 |
---|---|
[ Vue ] watch | watch로 객체를 감시하는 방법 (deep, .value, getter) (0) | 2024.10.01 |
[ Vue ] React와 Vue의 반응성 시스템의 공통점/차이점 (0) | 2024.09.30 |
[ Vue ] Vue 3의 반응성 시스템 (proxy 기반 자동 반응성) (0) | 2024.09.29 |
[ Vue ] defineProps로 정의한 props에 초기 값 설정하기 | withDefaults (0) | 2024.04.23 |