[컴] vue.js 에서 computed, method, watch

vuejs compute method watch 사용법

vue.js 에서 computed, method, watch

data

data: function(){...} 는 처음에 component 가 init 될 때 한번 호출된다. 그후엔 호출되지 않는다. 그러기에 watch 같은 것을 이용해서 computed 같은 효과를 주는 듯 하다.

computed vs method 사용법

기본적으로 rendering 이 될 때 template 안에서 사용되는 computed, methods 를 호출하게 된다. template 안에서 사용되지 않는 함수(computed, methods)라면 당연히 호출되지 않는다.

다음처럼 computed propertymethod 가 있다. 아래 같은 상황에서 2개는 똑같은 결과를 보여준다. 하지만 동작의 차이는 있다.

computed 는 그 ‘안에서 사용된 property’ 가 변할 때만 함수를 호출한다. 만약 ‘안에서 사용된 property’ 가 변하지 않았으면 값이 바뀌지 않을 것으로 판단하고, 이전의 값을 그대로 돌려준다.(computed properties are cached based on reactive dependencies)

하지만 ‘안에서 사용된 property’가 바꼈는지 상관없이 method 는 모조건 호출된다. 그래서 아래 코드에서 Date.now() 의 호출은 calculateBooksMessage 에서는 ’안에서 사용된 property’ 가 변할 때만 호출되지만, calculateBooksMessage2는 항상 호출된다.

<p>{{ calculateBooksMessage }}</p>
<p>{{ calculateBooksMessage2() }}</p>
Vue.createApp({
  data() {
    return {
      author: {
        name: 'John Doe',
        books: [
          'Vue 2 - Advanced Guide',
          'Vue 3 - Basic Guide',
          'Vue 4 - The Mystery'
        ]
      }
    }
  },
  computed: {
    // a computed getter
    calculateBooksMessage() {
      // `this` points to the vm instance
      const now = Date.now()
      return this.author.books.length > 0 ? 'Yes' + now : 'No'
    }
  },
  method: {
    calculateBooksMessage2() {
        const now = Date.now()
        return this.author.books.length > 0 ? 'Yes' + now : 'No'
    }
  }
}).mount('#computed-basics')

watch property

computed property 는 data 와 같은 것이라 봐도 무방하다. 그래서 2개는 내가 사용하고 싶은 data 를 선언하는 것이라고 보면 된다.

그런데 만약 이미 선언되어 있는 data 에 대해서 내가 그 데이터가 변할때 어떤 작업을 하도록 하고 싶다. 즉, 그 data가 변할 때 reactive 하게 무엇인가를 하고 싶다면 그 data 에 대해서 watcher 를 선언하면 된다.

그래서 watcher 의 key 이름은 우리가 observe 하려는 것의 이름을 가져야 한다. 그래서 만약 위처럼 calculateBooksMessage 를 사용하려면, 이 이름을 가진 data 가 존재해야 하고, 그 data 에 대한 watch 를 선언하는 것이다.

<p>{{ calculateBooksMessage }}</p>
<p>{{ calculateBooksMessage2() }}</p>
Vue.createApp({
  data() {
    return {
      author: {
        name: 'John Doe',
        books: [
          'Vue 2 - Advanced Guide',
          'Vue 3 - Basic Guide',
          'Vue 4 - The Mystery'
        ]
      },
      calculateBooksMessage: 'cal-message'
    }
  },
  watch: {
    // a computed getter
    calculateBooksMessage: function() {
      // `this` points to the vm instance
      const now = Date.now()
      return this.author.books.length > 0 ? 'Yes' + now : 'No'
    }
  },

}).mount('#computed-basics')

object 와 array값이 변경될 때 reactivity

자세한 이야기는 위 링크를 참고하자. 대략적으로 정리하면, array 값이 변경될 때는 splice 를 사용해야 인식한다. object 는 Object.assign({}, ...) 을 사용하던지, this.$set(this.someObject, 'b', 2) 를 사용해야 한다.

vue3 에서는 reactivity 의 breaking 에 대한 걱정을 하지 않아도 된다고 한다.(참고: vue.js - How do I do Vue.set() in Vue 3? - Stack Overflow)

ReactJS의 setState

개인적으로는 react 의 setState 를 호출하는 방식이 좀 더 명확해서 좋다. vuejs 는 대체로 스스로 알아서 setState 를 호출하는 식이긴 한데, 이것이 명확하게 보이지 않아서 개인적으로 debugging 하기가 힘들다.

여하튼, 그래서 vuejs 를 setState 을 호출하는 느낌으로 설명을 하자면, rendering 이 필요할 때 react 에서 setState 를 호출하는 것처럼 vuejs 에서는 <template> 안에서 사용되는 property 를 변경해야 한다. 그러니까 반대로 react 에서 setState 를 호출해야 하는 순간이라면 property 값을 변경하는 과정이 있으면 된다.

참고로, reactjs 처럼 key 를 변경해서 re-render 를 하게 하는 방법도 가능하다. 

key 를 이용해서 re-render 를 지시할 때 주의할 점

key가 변경되는 element 에 대한 rendering 을 다시할 때 그 element 의 props 를 새롭게 받아오지는 않는다는 것이다. key 를 가진 element 의 기존 props 를 이용해서 그 element 의 render() 를 호출한다. 만약 props 를 다시 받아서 rendering 을 해야 한다면, 그 부모 element 의 key 를 변경해야 한다.

Reference

  1. Methods, Computed, and Watchers in Vue.js | CSS-Tricks
  2. Computed Properties and Watchers — Vue.js : vue.js v2
  3. Computed Properties and Watchers | Vue.js: vue.js v3

댓글 없음:

댓글 쓰기