작성
·
502
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 방식으로 한, 이거에 동작 차이는 역시 아직도 의문이네요.