[VUE] WATCH

JIOO·2022년 12월 15일

Vue

목록 보기
8/18
post-thumbnail

✔ watch 메서드란 무엇인가?

Vue에서 데이터가 변경될 때 변화를 지켜보고 변화에 대응할 수 있다.

📃 참고문헌 https://ui.toast.com/weekly-pick/ko_20190307

기본내용 데이터명: {
  handler(value) {
   //value 바뀐내용
   console.log(value)
  }
}

### ** 🔎 추가내용 ** ** 데이터를 비동기로 가져올 때 예시**
export default {
 data() {
   return {
     question: '',
     answer: '질문에는 일반적으로 물음표가 포함됩니다.'
   }
 },
 watch: {
   // 질문이 변경될 때마다 이 함수가 실행됩니다
   question(newQuestion, oldQuestion) {
   // newQuestion = 바뀐데이터,원본데이터
     if (newQuestion.indexOf('?') > -1) {
     //newQuestion에 ?라는 문자가 포함 되어 있으면 getAnswer을 실행
       this.getAnswer()
     }
   }
 },
 methods: {
   async getAnswer() {
     this.answer = '생각 중...'
     try {
       const res = await fetch('answer을 가지고 오는 API')
       this.answer = (await res.json()).answer === 'yes' ? '네' : '아니오'
       //API를 가져와서 변수에 담고 싶을 때 await
     } catch (error) {
       this.answer = '에러! API에 연결할 수 없습니다. ' + error
     }
   }
 }
}
<div> 예/아니오 질문:</div>
 <input v-model="question" />
<p>{{ answer }}</p>

template나 메서드에서 데이터를 업데이트해야 한다면, data 안으로 들어가야 한다.
그 후의 속성 변경에 대한 응답으로 업데이트 해야 하는 경우 watch를 사용해야 한다.


중첩된 데이터 watch하기 - 배열 또는 객체

그럼, 실제로 watch가 필요한 경우라고 가정해보자.

그러나 배열이나 객체를 watch할 때, 예상했던 대로 동작하지 않는다.

무슨 일이 벌어지고 있는 거지?

몇가지 값이 포함된 배열을 만든다고 가정해 보자.

const array = [1, 2, 3, 4];
// array = [1, 2, 3, 4]
이제 더 많은 값을 넣어 배열을 업데이트하자.

array.push(5);
array.push(6);
array.push(7);
// array = [1, 2, 3, 4, 5, 6, 7]

질문이 있다. array가 변경되었는가?

글쎄, 그렇게 간단하지 않다.

배열의 내용은 변경되었지만, 변수는 여전히 같은 array 객체를 가리킨다. 배열 컨테이너는 변경되지 않았지만 배열 내부는 변경되었다. (const array = [] 랑 비슷하다고 보면된다)

const array = [] // array.push를 하면 배열 내부는 바뀌지만 배열자체는 바뀌지 않는다
const를 공부하다 보면 기존에 할당 된 값을 변경하는게 불가능 하다고 나와 있는데
const array안의 내부값을 바꾸는게 가능 한 이유도 이 때문이다

두 경우 다 재 할당 하는것이 아니기 때문에 가능하다.

따라서 Vue는 배열이나 객체를 watch할 때, 속성 내부가 변경되었다고 생각하지 않는다.
Vue에게 변경을 watch할 때 속성 내부를 검사하길 원한다고 알려줘야 한다.


다음과 같이 deep을 true로 설정하고 handler 메서드를 재배치 함으로써
Vue에게 원하는 바를 알려줄 수 있다.

export default {
  name: 'ColourChange',
  props: {
    colours: {
      type: Array,
      required: true,
    },
  },
  watch: {
    colours: {
      // This will let Vue know to look inside the array
      deep: true,

      // We have to move our method to a handler field
      handler()
        console.log('The list of colours has changed!');
      }
    }
  }
}

이제 Vue는 변경 사항을 watch할 때 속성 내부의 내용을 추적해야 함을 알 것이다.

그런데 handler 함수는 무엇일까?

조금 후에 handler에 대해 알아볼 것이다. 그 보다 우선 더 중요한 watch의 immediate에 대해 알아보자.

Immediate

watch는 속성의 값이 변할 때 실행되지만, 종종 변경과 관계없이 처음 한 번 실행해야 하는 경우가 있다.

다음은 movie속성의 설정에 따라 서버에서 데이터를 가져오는 MovieData 컴포넌트 예제이다.


export default {
  name: 'MovieData',
  props: {
    movie: {
      type: String,
      required: true,
    }
  },
  data() {
    return {
      movieData: {},
    }
  },

  watch: {
    // Whenever the movie prop changes, fetch new data
    movie(movie) {
      // Fetch data about the movie
      fetch(`/${movie}`).then((data) => {
        this.movieData = data;
      });
    }
  }
}

이 컴포넌트는 훌륭하게 작동한다.
movie 속성이 변경할 때마다 watch가 실행되고 새로운 데이터를 가져온다.

여기에 작은 문제가 있다는 것만 빼고는 잘 동작한다.

문제는 페이지가 로드 될 때 movie가 기본값으로 설정된다는 것이다.
그러나 속성이 아직 변경되지 않았으므로 watch는 실행되지 않는다.
다른 동영상을 선택할 때까지 데이터가 로드되지 않음을 의미한다.


그렇다면 페이지 로드 시 즉시 watch가 실행되도록 할 수 있을까?

immediate를 true로 설정하고 핸들러 함수를 아래처럼 옮긴다.


watch: {
  // Whenever the movie prop changes, fetch new data
  movie: {
    // Will fire as soon as the component is created
    immediate: true,
    handler(movie) {
      // Fetch data about the movie
      fetch(`/${movie}`).then((data) => {
        this.movieData = data;
      });
    }
  }
}

자, 여러분은 handler 함수를 두 번이나 보았다. 이제 그게 무엇인지 다룰 때가 되었다.

profile
프론트엔드가 좋은 웹쟁이 with Notion (요즘은 노션과 병행 중)

0개의 댓글