• 카테고리

    질문 & 답변
  • 세부 분야

    프론트엔드

  • 해결 여부

    미해결

@Watch 질문 드립니다!

19.06.17 13:07 작성 조회수 374

1

안녕하세요? watch 속성 질문 드립니다.

 

<div>
<p>
@Watch
</p>
<button @click="changeMessage">메세지 변경</button>
<div>{{cMsg}}</div>
</div>

 

import { Component, Vue, Watch } from 'vue-property-decorator';
export default class Home extends Vue {
public message: string = 'hello children';
public cMsg: string | undefined;
public alertMsg: string = '변경이 감지되었습니다.';

// immediate : 즉시 호출하겠다는 의미.
// deep : object 내의 속성값까지 감시.
// @Watch('cMsg', {immediate: true, deep: true})
@Watch('cMsg')
public watchAlertMsg(value: string | undefined, oldValue: string | undefined) {
console.log(value);
console.log(oldValue);
alert(this.alertMsg);
}

public changeMessage() {
this.cMsg = 'change';
}

}

 

위와 같이 코딩을 했는데, 

cMsg 상태변수에 '' 이런식으로 초기화를 해둔경우는 정상적으로 동작을 하는데,

위와 같이 하면 왜 변경감지가 안되는지 알고싶습니다.

TS를 사용안한 vue에서는 테스트를 해보지는 못했습니다..ㄷㄷ

 

public cMsg: string | undefined = '';

위와 같이 초기화를 해주면,

옆에 사진과 같이, 해당 컴포넌트 상태변수로 존재합니다. 

= ''; 구문을 빼면, 상태변수 자체도 안보이구요

 

제가 TS구문을 잘 몰라서 이런거 같기는 한데.. 

public cMsg: string | undefined

해당 상태변수에 문자열 또는 undefined 가 할당이 될수 있어 이거 아닌가요? 그러면 제 생각은

cMsg = undefined; 이런거니 여기서 값이 바뀌면 감지가 되야 하는거같은데..ㅠㅠ 어렵네요

 
 
watch: {
testWatch(after, before) {
console.log('감지?');
console.log(before);
console.log(after);
}
},

data() {
return {
testWatch : undefined,
};
}

위 와 같이 하면, 정상적으로 감지(값을 변경할때마다)가 되어서 watch 속성 콜백함수가 호출이 됩니다.

TS 당신은 왜..ㅠㅠ

답변 2

·

답변을 작성해보세요.

1

안녕하세요! ChangHyeon Bae님!

Watch는 데이터의 변경을 관찰합니다.

질문 주신 케이스에서 Watch가 동작하지 않는 이유는,
cMsg라는 속성이 없기 때문입니다. 없는 속성에 Watch를 설정해놓은 것과 마찬가지지요.

public cMsg: string | undefined ;

위와 같이 분명히 선언했는데 왜 없을까요?

그 이유는, vue-cli로 코드를 빌드하면, webpack과 ts-loader로
타입스크립트 문법을 자바스크립트로 컴파일을 하게 됩니다.
이 때 프로퍼티를 확인해서 값이 할당된 프로퍼티만 객체의 속성으로 추가하기 때문입니다.

public cMsg: string | undefined = undefined;

또한 위와 같은 코드도 동일하게 동작하지 않습니다.

Vue 공식 문서에서 아래와 같이 설명하고 있습니다.

"Vue는 루트 수준의 반응성 속성을 동적으로 추가 할 수 없으므로
모든 루트 수준의 반응성 데이터 속성을 빈 값으로라도 초기에 선언하여 Vue 인스턴스를 초기화해야합니다."

export default class Home extends Vue {
public cMsg: string | undefined;

created() {
// undefined;
console.log(this);
}
}

위와 같이 created hook에서 this를 콘솔로 출력해보면,
cMsg라는 속성은 없는것을 확인하실 수 있습니다.

그래서 이로인해 발생하는 문제점을 막기 위해 타입스크립트에서는
tsconfig.json에 특별한 설정을 하지 않거나, !를 붙이지 않은 클래스 프로퍼티에 대해서는
에러를 발생하고 있습니다.

@Prop과 같이 특수한 경우가 아닐때는 반드시 undefined가 아닌 값으로 초기화 해주시기 바랍니다.
(공통된 빈값이 필요한 경우에는 null을 사용하세요.)

참고로, changeMessage라는 메서드에서 값을 할당하고 있긴 하지만,
이 경우에는 값을 수정하는것이 아닌 속성을 "추가"하는 것입니다!

Vue의 Watch는 속성의 추가/제거에 대해 감지할 수 없는 한계를 가지고 있습니다.
(자세한 내용은 https://kr.vuejs.org/v2/guide/reactivity.html<- 링크를 방문하세요.)

0

친절한 답변 정말로 감사합니다!

결론은 data 옵션에 해당 상태변수 자체가 존재하지 않는 상태에서 watch를 걸어버린거네요 ㅠㅠ

 

그래도 여전히 읽어보면서 의문인건.

 

public cMsg: string | undefined = undefined;

TS로 초기화 해준 undefined와

 

<template>
<div>
<button @click="changeValue">
watch 감지!
</button>
</div>
</template>

<script>
export default {
name: "Watch",

watch : {
changeVal(value, oldValue) {
console.log('감지?');
console.log(value);
console.log(oldValue);
},
},

data(){
return {
changeVal : undefined
}
},

methods : {
changeValue() {
this.changeVal = Math.floor(Math.random() * 10) + 1; // 1 ~ 10 난수 생성
}
}
}
</script>

<style scoped>

</style>

SFC 방식으로 한, 이거에 동작 차이는 역시 아직도 의문이네요.