본문 바로가기
front/vue

[vue] watch()

by juniKang 2022. 8. 8.

watch는 하나 이상의 반응형 데이터소스를 감시하고, 소스가 변경되었을 때 콜백 함수를 호출합니다.

 

Type

// 하나의 소스를 감시합니다.
function watch<T>(
  source: WatchSource<T>,
  callback: WatchCallback<T>,
  options?: WatchOptions
): StopHandle

// 여러개의 소스를 감시합니다.
function watch<T>(
  sources: WatchSource<T>[],
  callback: WatchCallback<T[]>,
  options?: WatchOptions
): StopHandle

type WatchCallback<T> = (
  value: T,
  oldValue: T,
  onCleanup: (cleanupFn: () => void) => void
) => void

type WatchSource<T> = 
  | Ref<T> // ref
  | (() => T) // getter
  | T extends object ? T : never // reactive object
  
interface WatchOptions extends WatchEffectOptions {
  immediate?: boolean // default: false
  deep?: boolean // default: false
  flush?: 'pre' | 'post' | 'sync' // default: 'pre'
  onTrack?: (event: DebuggerEvent) => void
  onTrigger?: (event: DebuggerEvent) => void
}

(타입은 가독성을 위해 단순화 되었다)

Details

watch()는 기본적으로 lazy이다 - 그래서 콜백은 감시중인 소스가 변경되면 호출된다.

 

첫 번째 아규먼트는 감시할 소스이다. 소스는 다음 중 하나가 될 수 있다.

  • 값을 리턴하는 getter 함수
  • ref
  • reactive object
  • ... 또는 위 3가지의 배열

두 번째 아규먼트는 소스가 변경되었을 때 호출할 콜백이다. 콜백은 세가지 아규먼트를 받는다: 새로운 값, 이전 값, 사이드 이펙트 클린업 콜백을 등록하기위한 함수. 클린업 콜백은 이펙트가 다시 실행되기 바로 직전에 호출될 것이다. 그리고 유효하지 않은 사이드 이펙트를 클린업하기 위해 사용된다. 즉, 비동기 요청에 달려있다.

 

여러개의 소스를 감시할 때, 콜백은 소스배열에 상응하는 새로운 / 오래된 값을 담고있는 두개의 배열을 받는다. 

 

세 번째 옵셔널 아규먼트는 다음 옵션들을 지원하는 옵션 객체 이다:

  • immediate: watcher가 생성되면 즉시 콜백을 트리거한다. 첫 호출에서 이전 값은 undefined이다.
  • deep: 소스가 객체라면 소스의 하위 프로퍼티까지 깊게 감시한다. 하위 프로퍼티의 상태변화에도 콜백을 호출한다.
  • flush: 콜백의 플러시 타이밍을 조정한다.
  • onTrack / onTrigger: 왓쳐의 의존성들을 디버그한다.

watchEffect()와 비교하여, watch()는 다음이 가능하다:

  • 사이드 이펙트를 lazy로 수행한다.
  • 왓쳐의 콜백함수를 실행시키기위한 트리거로 보다 상세한 소스를 지정할 수 있다.
  • 감시중인 상태의 현재값과 이전값 둘 다 접근할 수 있다.

Example

getter를 감시할 때:

const state = reactive({ count: 0 })
watch(
  () => state.count,
  (count, prevCount) => {
    /* ... */
  }
)

ref를 감시할 때:

const count = ref(0)
watch(count, (count, prevCount) => {
  /* ... */
})

여러개의 소스를 감시할 때, 콜백은 소스배열에 상응하는 new/ old 값들을 담고있는 배열을 받는다.

watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
  /* ... */
})

getter 소스를 실행할 때, 왓쳐는 오직 getter의 리턴값이 변경되었을 때만 실행한다. 만약 깊은 상태변화에도 콜백을 실행시키기 원한다면, 명시적으로 { deep: true } 로 deep 모드를 강제해야 한다. deep 모드에서는, 깊은 상태변화에 의해 트리거 되었을 때 콜백의 새로운 값과 이전값이 같은 객체일 것이다=:

const state = reactive({ count: 0 })
watch(
  () => state,
  (newValue, oldValue) => {
    // newValue === oldValue
  },
  { deep: true }
)

reactive object를 직접적으로 감시할 때, watcher는 자동적으로 deep mode이다:

const state = reactive({ count: 0 })
watch(state, () => {
  /** triggers on deep mutation to state */
})

watch()는 watchEffect()와 플러시 타이밍과 디버깅 옵션을 공유한다:

watch(source, callback, {
  flush: 'post',
  onTrack(e) {
    debugger
  }
})

'front > vue' 카테고리의 다른 글

[vue] TransitionGroup  (0) 2022.08.08
[vue] Transition  (0) 2022.08.08
[vue] ref, reactive 반응형  (0) 2022.08.07
[vue] app.mount()  (0) 2022.07.30
[vue] setup()  (0) 2022.07.30

댓글