IT/언어

[Vue.js] watch 오브젝트 (handler 유무, deep, immediate등)

개발자 두더지 2023. 1. 15. 23:32
728x90

일본의 한 블로그 글을 번역한 포스트입니다. 오역 및 의역, 직역이 있을 수 있으며 틀린 내용은 지적해주시면 감사하겠습니다.

 

  Vue.js에서 사용할 수 있는 편리한 기능 중 하나로 "watch" 오브젝트가 있다. watch가 지정한 프로퍼티의 값을 감시하여 변경이 있으면, 지정한 처리를 자동적으로 실행해주는 것이다.

 watch에는 handler이나 deep, immediate이라는 키워드가 기재가 되어 있는 경우와 없는 경우가 있다. hanlder는? deep, immediate는? 그리고 있는 경우랑 없는 경우, watch 처리가 어떻게 바뀌는거지? 의문을 가지는 사람들이 있을 것이다.

 여기에서는 watch의 handler나 depp, immediate 처리에 대해서 실례에 대해 살펴보고 해설하고자 한다.

 

 

hanlder나 deep, immediate는 무엇인가?


  handler을 이해하기 전에 먼저 depp이나 immediate에 대해 이해할 필요가 있다.

 

deep이나 immediate이란?

 deep과 immediate는 watch 오브젝트의 옵션이다. 이 업션을 사용하면 watch의 처리가 다음과 같이 바뀐다.

옵션 처리내용
deep 지정한 속성 안에 있으며, 지정한 속성 프로퍼티의 값도 감시한다.
immediate watch의 처리를 페이지를 페이지 읽어들일 때도 실행한다.

 또한, 옵션은 여러 개 동시에 설정하는 것도 가능하다.

deep

watch는 디폴트의 상태면, 지정한 속성의 값만 감시한다. deep을 속성을 추가하면, 지정한 속성안에 있는 속성의 값, 안에 삽인된 속성의 값도 감시한다.

immediate

watch는 기본적인 상태라면 페이지를 읽어들었을 시점에는 처리가 실행되지 않는다. 무언가의 변화가 알았을 때에 처음에 처리가 발동한다.

 immediate 옵션을 붙이면, 처음 페이지를 읽어들였을 때 순간에 지정한 watch의 처리를 싱행하는 것이 가능하다.

 

그럼 handler이란 무엇인가?

 handler는 deep이나 immediaet등의 옵션을 사용할 때에 필요한 오브젝트이다. handler이란, 처리가 어디에 있는지를 표시하기 위해서 지정하는 메소드명이다. 상세한 내용은 옵션이 있는 watch와 옵션이 없는 watch를 비교하면 알기 쉽다.

옵션이 없는 watch

보통 옵션이 없는 watch의 기재는 아래와 같다. 여기서는 handler가 나오지 않는다.

watch:{
  감시할 속성명( 새로운값을 넣을 변수, 이전 값을 넣을 변수 ){
    처리
  }
}

옵션이 있는 watch

watch:{
  감시할 속성명: {
    handler( 새로운 값을 넣을 변수, 이전 값을 넣을 변수 ){
      처리
    },
   옵션명: 참거짓값
  }
}

 옵션은 watch로 실행할 처리 내용과 병렬로 작성할 필요가 있다. 옵션이 없는 watch의 기재 내용 중에 옵션을 쓰려고 하면, 쓸 장소가 마땅치않다(처리중에 옵션을 설정하면, 처리의 일부로 간주되어 버린다).

 그러므로, 어떤 것이 처리인가를 표시하는 메소드명으로서 handler을 설치한다. 그렇게 함으로써 처리내용에 있는 handler과 옵션이 위에 작성한 코드와 같이 병렬로 기재할 수 있게 된다.

 

 

인수의 생략


 watch 옵션에서는 처리에 대해서 아래와 같이 인수를 두 개 기재하고 있다.

감시할 속성명( 새로운 값을 넣을 변수, 이전 값을 넣을 변수 )

handler( 새로운 값을 넣을 변수, 이전 값을 넣을 변수 )

 

두 가지 인수 다 필요없는 경우

두 가지 인수는 필수가 아니다. 처리 중에 "새로운 값"도 "이전 값"도 사용할 필요가 없는 경우는 인수를 기재할 필요가 없다.

watch:{
  감시할 속성명(){
    처리
  }
}

 또한, 제 1인수와 제 2 인수 기재해 놓고 사용하지 않아도 문제는 없다.

 

새로운 값만 필요한 경우

새로운 값만 사용하고 싶은 경우, 제 1 인수에만 기재하면 된다.

watch:{
  감시할 속성명: function( 새로운 값을 넣을 변수 ){
    처리
  }
}

 

이전 값만 필요한 경우

 이전 값만 필요한 경우는 제 1인수와 제 2 인수 양쪽 모두 작성할 필요가 있다. 처리중에 제1인수는 안쓰면 된다.

 

 

deep의 사용예


작성법

watch:{
  감시할 속성명: {
    handler( 새로운 값을 넣을 변수, 이전값을 넣을 변수 ){
      처리
    },
   deep: true
  }
}

포인트는 다음과 같다.

  • handler로 처리를 기재한다.
  • 새로운 값은 제 1 인수에 넣고, 이전 값은 제 2인수에 넣는다(인수는 생략가능).
  • deep 옵션을 지정한다(값은 true).

 

예시

data 오브젝트 안에,  포함된 속성이 있는 user이라는 속성을 셋팅하여 v-model을 사용하여 input으로 쌍방향 바인딩한다.

 user 속성의 안의 속성성 값에 어떠한 변경이 있고, 그 변경을 검지하기 위해서는 depp 옵션을 사용할 필요가 있다.

var app = new Vue({
  el:"#app",
  data:{
    user: {
      name: 'Steve',
      age: '28',
      homeTown: '서울' 
    }
  },
  watch:{
    user: {
      handler( newVal, oldVal ){
        console.log( 'newVal:', newVal, 'oldVal:', oldVal )
      },
      deep: true
    }
  }
})

 user 속성의 값을 감시하여 변경이 있으면 콘솔에 새로운 값을 "newVal"의 옆에 표시하고 이전의 값는 "oldVal"의 옆에 표시하는 프로그램이다. 

<body>
  <div id="app">
    
    <p><input type="text" v-model.lazy="user.name" ></p>

  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>

 v-model에는 lazy 수식자를 붙여, 하나의 문자마다의 변경이 아닌 입력 확정만을 검출하도록 한다.

 

 

immediate의 사용예


 immediate  옵션을 사용하면 변경이 있는 경우만이 아니라 페이지가 읽어들였을 때에 처리를 실행하는 것이 가능하다.

watch:{
  감시할 속성명: {
    handler( 새로운 값을 넣은 변수명, 이전 값을 넣을 변수명 ){
      처리
    },
   immediate: true
  }
}

 포인트는 다음과 같다.

  • handler로 처리를 기재한다.
  • 새로운 값은 제 1 인수에 넣고, 이전의 값은 제 2 인수에 넣는다(인수는 생략가능).
  • immediaet 옵션을 설정한다(값은 true).

 

depp 옵션과의 병용

아래와 같이 deep 옵션과 병용하는 것도 가능하다.

watch:{
  감시할 프로퍼티 속성명: {
    handler( 새로운 값을 넣을 변수, 이전 값을 넣을 변수 ){
      처리
    },
   deep: true,
   immediate: true
  }
}

 

 

[참고] watch immediate:true의 라이프 사이클 어디서 실행되는가?


 watchsms 보통 감시를 시작해 데이터가 변항 직후에 콜백이 호출되지만, immediate 옵션이 붙은 watchsms 감시를 시작한 직후에 한 번 콜백이 호출된다.

 또한, Vue에는 인스턴스의 라이프사이클에 맞춰 함수를 실행하는 라이프 사이클 후크라는 구조가 있다. 여기서 immediaet 옵션이 붙은 watch는 라이프사이클에서 어던 타이밍에 호출될까? 이라는 의문이들어 이 부분을 조사해봤다.

 아래의 코드를 실험삼아 실행하보면, immediate가 붙은 watch는 deforeCreate와 created 사이에서 실행됐다.

new Vue({
  el: '#app',
  data: function() {
    return {
      helloWorld: 'HelloWorld'
    };
  },
  beforeCreate: function() {
    console.log('call beforeCreate');
  },
  created: function() {
    console.log('call created');
  },
  mounted: function() {
    console.log('call mounted');
  },
  watch: {
    helloWorld: {
      handler: v => console.log('call watch', v),
      immediate: true
    }
  }
})
call beforeCreate
call watch HelloWorld
call created
call mounted

 라이프 사이클 그림에 빗대어서 말하자면 Init Injections  & Reactivity에서 Watch가 구동되는 것이다.


참고자료

https://qiita.com/sin_tanaka/items/64b4a48bcb6dac924380

https://prograshi.com/language/vue-js/what-are-handler-deep-and-immediate-in-watch/

728x90