감시자(watcher)
이미 정해져 있는 속성들은 template에서 사용할 수 있습니다. 그러나 속성 값이 변하게 되면 랜더링을 수행하여 화면을 나타내야 하는데 이때 watch
옵션을 사용하여 반응형 속성이 변경될 때마다 함수를 실행할 수 있습니다.
export default {
data() {
return {
question: '',
answer: '질문에는 일반적으로 물음표가 포함됩니다.'
}
},
watch: {
// question이 변경될 때마다 이 함수가 실행됩니다
question(newQuestion, oldQuestion) {
if (newQuestion.includes('?')) {
this.getAnswer()
}
}
},
methods: {
async getAnswer() {
this.answer = '생각 중...'
try {
const res = await fetch('https://yesno.wtf/api')
this.answer = (await res.json()).answer === 'yes' ? '네' : '아니오'
} catch (error) {
this.answer = '에러! API에 연결할 수 없습니다. ' + error
}
}
}
}
<p>
예/아니오 질문:
<input v-model="question" />
</p>
<p>{{ answer }}</p>
1. Deep Wacher(깊은 감시자)
감시되는 프로퍼티에 새 값이 할당되었을 때만 감지하며 중첩된 프로퍼티 변경에는 감지하지 않습니다. 프로퍼티 내부의 중첩된 값 변경을 감지하려면 Deep Wather를 사용해야 합니다.
단, Deep Wacher는 객체의 모든 중첩 속성을 탐색하기 때문에 큰 데이터 구조에서 사용할 때 비용이 많이 들 수 있습니다. 성능을 고려하여 필요한 경우에만 사용하는 것이 좋습니다.
export default {
watch: {
someObject: {
handler(newValue, oldValue) {
// 참고:
// someObject가 다른 객체로 교체되지 않는 한,
// newValue와 oldValue는 같습니다.
// 둘 다 동일한 객체를 참고하고 있기 때문입니다!
},
deep: true
}
}
}
2. Eager Watchers
watch
는 기본적으로 lazy 한 특징을 갖고 있어 콜백은 감시된 속성이 변경되기 전까지 호출되지 않습니다. 최초 데이터가 구성된 후 콜백이 실행되길 원한다면(eager) handler
함수와 immediate:true 옵션으로 구성된 객체를 사용해 감시자를 선언하여 즉시 실행되도록 할 수 있습니다.
export default {
// ...
watch: {
question: {
handler(newQuestion) {
// 이제 컴포넌트 생성 시
// `beforeCreate`와 `created` 훅 사이에
// 한 번 실행됩니다.
},
// eager(즉시)으로 콜백 실행
immediate: true
}
}
// ...
}
3. 콜백 실행 타이밍
반응형 상태를 변경하게 되면 Vue 컴포넌트 업데이트와 사용자가 만든 감시자 콜백이 모두 실행되는데 기본적으로 개발자가 생성한 감시자 콜백은 Vue 컴포넌트가 업데이트되기 이전에 실행됩니다. 때문에 감시자 콜백 내에서 DOM에 접근하면 DOM이 Vue에 의해 업데이트되기 이전의 상태입니다.
Vue에 의해 업데이트된 후 DOM을 감시자 콜백에서 접근하고자 할 때, flush: 'post'
옵션을 지정하여 접근할 수 있습니다.
export default {
// ...
watch: {
key: {
handler() {},
flush: 'post'
}
}
}
기본적으로 flush: 'pro' | 'post'
옵션은 콜백을 버퍼링 하기 때문에 동일한 틱(tick)에서 여러 번 상태 변경이 되더라도 마지막에 한 번만 호출되는 특징이 있습니다. 만약 동일한 틱 내에 상태 변경 시마다 동기적으로 콜백을 호출해야 하는 경우 flush: 'sync'
옵션을 사용할 수 있습니다.(단, 일반적으로 sync 옵션은 비효율적이기 때문에 정말 사용하는데 필요한 경우인지 고려해 주세요)
export default {
data: () => ({ count: 0 }),
watch: {
count: {
handler(val, preVal) {
console.log('변경이 감지됨!', val, preVal)
},
flush: 'sync'
}
},
methods: {
increment() {
this.count++
// 이어서 callback이 실행됨
this.count++
// 역시 callback이 실행됨
this.count++
// 또 callback이 실행됨
}
}
}
4. $watch() 인스턴스 메서드
$watch()
인스턴스 메서드를 사용하여 감시자를 선언적으로 생성할 수 있습니다. 감시자를 조건부로 사용할 때나, 사용자 상호 작용에 대한 응답으로만 무언가를 감시해야 할 때 사용합니다. 또한 감시자를 도중에 중지할 수도 있습니다.
export default {
created() {
this.$watch('question', (newQuestion) => {
// ...
})
}
}
// 감시자 중지
const unwatch = this.$watch('foo', callback)
// ...나중에 감시자가 더 이상 필요하지 않을 때:
unwatch()
'Front-End > Vue.js' 카테고리의 다른 글
[Vue] - Components Communication(props, emit) (0) | 2023.02.12 |
---|---|
[Vue] - 템플릿 참조 (0) | 2023.02.12 |
[Vue] - 컴포넌트 생명주기(created, mounted, updated) (0) | 2023.02.12 |
Vue - Form 입력 바인딩 (0) | 2023.02.03 |
Vue - 조건부, 리스트 렌더링과 이벤트 핸들링 (0) | 2023.01.29 |
댓글