[vue] watchers

Published: by Creative Commons Licence

참고

vue 왓쳐

watchers

DOM을 변경시킨다거나 비동기 조작 결과에 따라 상태를 변화시켜야 하는 경우와 같이, 상태 변화에 맞춰 추가적인 기능이 필요할 때 watch 옵션을 사용한다. 기본 사용법은 computed옵션과 같이 data() 내 선언된 변수명과 동일한 함수명으로 함수를 정의하여 사용한다.

기본 사용법

watch옵션의 question함수는 question프로퍼티의 값이 변경될때마다 실행이 된다. 질문에 ?가 있으면 getAnswer함수가 호출되고 비동기 통신 후 결과값을 p태그에 바인딩되어 있는 answer프로퍼티에 넣는다.

export default {
  data() {
    return {
      question: '',
      answer: 'Questions usually contain a question mark. ;-)'
    }
  },
  watch: {
    question(newQuestion, oldQuestion) { // 'some.nested.key(newValue) {}' 와 같이 '.'으로 연결된 경로로도 된다고 하는데 잘???
      if (newQuestion.includes('?')) {
        this.getAnswer()
      }
    }
  },
  methods: {
    async getAnswer() {
      this.answer = 'Thinking...'
      try {
        const res = await fetch('https://yesno.wtf/api')
        this.answer = (await res.json()).answer
      } catch (error) {
        this.answer = 'Error! Could not reach the API. ' + error
      }
    }
  }
}
<p>
  Ask a yes/no question:
  <input v-model="question" />
</p>
<p></p>

Deep Watchers

watch는 기본적으로 중첩문의 프로퍼티까지 감시하진 않는다. 중첩 프로퍼티의 값변화까지 감시하려면 Deep Watcher를 사용해야 한다. deep: true 옵션을 추가하면 된다. 추가로 더 알아봐야할듯…

비용이 많이 드니 꼭 필요한 경우에만 사용할 것.

export default {
  watch: {
    someObject: {
      handler(newValue, oldValue) {
        // Note: `newValue` will be equal to `oldValue` here
        // on nested mutations as long as the object itself
        // hasn't been replaced.
      },
      deep: true
    }
  }
}

Eager Watchers

watch는 기본적으로 프로퍼티의 변화가 있을때만 호출이 되는데, 컴포넌트가 생성되자 마자 첫 실행을 하고 이후 값 변화가 있을 때마다 추가 호출이 되게 하고 싶으면 Eager Watcher를 쓰면 된다. handler()함수와 immediate: true 옵션을 추가하면 된다.

export default {
  // ...
  watch: {
    question: {
      handler(newQuestion) {
        // this will be run immediately on component creation.
      },
      // force eager callback execution
      immediate: true
    }
  }
  // ...
}

Callback Flush Timing

watch에 정의한 콜백함수는 뷰 컴포넌트가 업데이트 되기 전에 호출이 된다. 따라서 콜백에서 DOM에 접근을 한다면 업데이트 전의 상태로 접근을 한다는 의미이다. 만약 뷰 컴포넌트가 업데이트 되고 난 이후에 watcher 콜백에서 DOM에 접근하고 싶다면 flush: 'post'을 사용하면 된다.

export default {
  // ...
  watch: {
    key: {
      handler() {},
      flush: 'post'
    }
  }
}

this.$watch()

$watch()로 함수를 만들 수 있다. 이거은 조건에 따라 watcher를 세팅하고 싶을때나 사용자 반응에 따라 뭔가를 감시하고싶을 때 유용하다. 또한 watcher를 일찍 중단할 때도 사용할 수 있다.

export default {
  created() {
    this.$watch('question', (newQuestion) => {
      // ...
    })
  }
}

Watcher 중단

Watcher는 watch옵션이나 $watch()인스턴스 메소드로 선언할 수 있는데 이것은 소유자 컴포넌트가 unmounted 되었을 때 자동적으로 중단된다. 따라서 대부분의 경우에는 중단할 필요가 없다. 하지만 드문 경우로 강제로 중단을 해야 할 필요가 있는데 이때는 $watch()메소드의 리턴값을 이용하면 된다.

const unwatch = this.$watch('foo', callback)

// ...when the watcher is no longer needed:
unwatch()