체인의정석

Vue.js computed와 watch 본문

개발/frontend

Vue.js computed와 watch

체인의정석 2020. 6. 19. 11:40
728x90
반응형

computed 속성

mustach {{ }} 안에 표현식을 넣으면 편리하지만 이는 간단한 연산에만 한정됩니다.
따라서 복잡한 표현식이 들어가는 경우에는 computed속성을 사용해야 합니다.

<div id="example">
      <p>원본 메시지: "{{ message }}"</p>
      <p>역순으로 표시한 메시지: "{{ reversedMessage }}"</p>
</div>

var vm = new Vue({
  el: '#example',
  data: {
    message: '안녕하세요'
  },
  computed: {
    // 계산된 getter
    reversedMessage: function () {
      // `this` 는 vm 인스턴스를 가리킵니다.
      return this.message.split('').reverse().join('')
    }
  }
})

다음과 같이 메세지가 표시됨을 확인하였습니다.

이렇게 되었을때의 요점은 바인딩된 데이터에 따라서 업데이트가 이루어진다는 점입니다.

copmputed 속성의 캐싱 VS 메소드

표현식에서 메소드를 호출하여 같은 결과를 얻을 수도 있습니다.

computed속성 대신 메소드와 같은 함수를 정의하여 사용하는 방식도 있습니다.
차이점은 computed 속성은 종속 대상을 따라 저장 된다는 것입니다.

computed는 바인딩된 데이터가 변경되지 않는 이상 계산을 다시 실행하지 않고 결과를 즉시 반환 합니다.
아무곳에도 의존하지 않는 Date.now()는 따라서 절대로 업데이트 되지 않습니다.

캐싱의 경우 반복되는 계산을 줄이는데 이용될 수 있으며 캐싱이 필요하지 않은 경우에는 computed메서드를 사용하는 대신에 메소드를 사용하는 방법이 있습니다.

computed 속성 vs watch 속성

뷰에서는 watch속성을 제공하지만 computed 속성이 더 좋다고 합니다.

watch의 경우에는 경우에 따라 데이터가 바뀌면 어떤 함수를 실행할지 모두 지정해주는 명령형 프로그래밍이고 computed의 경우에는 정의를 해버리는 방식으로 선언형 프로그램이기 때문입니다.

computed 속성의 setter 함수

computed속성은 기본적으로 getter 함수만 가지고 있지만 필요한 경우에는 setter 함수도 만들어서 사용할 수 있다고 합니다.

// ...
computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}
// ...

이제 vm.fullName = 'John Doe'를 실행하면 설정자가 호출되고 vm.firstName vm.lastName이 그에 따라 업데이트 됩니다.

 

computed로 특정 변수를 가져오는 경우 set을 통하여 받은 변수를 자동으로 업데이트 시킬 수 있음을 알 수 있었습니다. 블록체인에서 정보를 조회할 때도 computed로 여러 정보가 담긴 객체를 반환할때 setter를 사용하면 각각 객체에 대한 정보를 정의시킬 수 있을것 같습니다.

watch 속성

대부분의 경우 computed 속성이 더 적합하지만 사용자가 만든 감시자가 필요한 경우가 있습니다. 그래서 Vue는 watch 옵션을 통해 데이터 변경에 반응하는 보다 일반적인 방법을 제공합니다. 이는 비동기식이거나 시간이 많이 소요되는 조작을 수행하려는 경우에 가장 유용합니다.

<div id="watch-example">
<p>
  yes/no 질문을 물어보세요:
  <input v-model="question">
</p>
<p>{{ answer }}</p>

Watch를 이용하여 yes/no 질문을 한다면, 데이터의 상태에 따라서 다른 표시를 해줄 수 있습니다.

  <!-- 이미 Ajax 라이브러리의 풍부한 생태계와 범용 유틸리티 메소드 컬렉션이 있기 때문에, -->
<!-- Vue 코어는 다시 만들지 않아 작게 유지됩니다. -->
<!-- 이것은 이미 익숙한 것을 선택할 수 있는 자유를 줍니다. -->
<script src="https://unpkg.com/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://unpkg.com/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
  el: '#watch-example',
  data: {
    question: '',
    answer: '질문을 하기 전까지는 대답할 수 없습니다.'
  },
  watch: {
    // 질문이 변경될 때 마다 이 기능이 실행됩니다.
    question: function (newQuestion) {
      this.answer = '입력을 기다리는 중...'
      this.getAnswer()
    }
  },
  methods: {
    // _.debounce는 lodash가 제공하는 기능으로
    // 특히 시간이 많이 소요되는 작업을 실행할 수 있는 빈도를 제한합니다.
    // 이 경우, 우리는 yesno.wtf/api 에 액세스 하는 빈도를 제한하고,
    // 사용자가 ajax요청을 하기 전에 타이핑을 완전히 마칠 때까지 기다리길 바랍니다.
    // _.debounce 함수(또는 이와 유사한 _.throttle)에 대한
    // 자세한 내용을 보려면 https://lodash.com/docs#debounce 를 방문하세요.
    getAnswer: _.debounce(
      function () {
        if (this.question.indexOf('?') === -1) {
          this.answer = '질문에는 일반적으로 물음표가 포함 됩니다. ;-)'
          return
        }
        this.answer = '생각중...'
        var vm = this
        axios.get('https://yesno.wtf/api')
          .then(function (response) {
            vm.answer = _.capitalize(response.data.answer)
          })
          .catch(function (error) {
            vm.answer = '에러! API 요청에 오류가 있습니다. ' + error
          })
      },
      // 사용자가 입력을 기다리는 시간(밀리세컨드) 입니다.
      500
    )
  }
})
</script>

 

정리를 하자면 다음과 같습니다.

 

1. computed 속성이라는 것이 있는데 이를 새용하면 데이터가 캐시 되어서 동일한 호출이 반복될 때 사용하면 된다.

2. setter를 이용하게 되면 불러오는 변수에 setting을 해서 getter함수를 대체하여 원하는 대로 만들어 쓸 수 있다.

3. 기본적으로 computed를 사용하는것이 더 좋다. 그러나 watch를 쓰면 좋은 경우가 있는데 특정 작업에 시간이 오래 걸려서 비동기처리를 해야하는 경우가 이에 해당된다. watch를 써서 각 상황에 어떤 결과가 나오게 할지 설정하면 된다. 한마디로 watch를 사용하게 되면 API와 비동기연산을 할때 중간 상태를 설정해 줄 수 있게 된다. 블록체인 API의 경우에는 응답하는데 시간이 오래 걸리는 케이스가 많기 때문에 watch의 사용을 하게 되면 중간상태에 대한 표시를 더 효율적으로 해줄 수 있을 것으로 보인다.

 

 

728x90
반응형
Comments