deep watch
deep watch
감시자를 이용하다 보면 객체나 배열을 감시해야 하는 경우가 발생한다. 이 때 일반적인 감시자를 이용하면 정상적으로 감시가 이루어지지 않는 상황이 발생한다.
아래의 예제를 통해 확인한다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue deep watch</title>
<style>
* {
box-sizing: border-box;
font-size: 15px;
}
textarea{
resize: none;
padding:0.5em;
}
input{
padding:0.5em;
}
</style>
</head>
<body>
<div id="app">
<label>
title<br>
<input type="text" v-model="board.title">
</label>
<br><br>
<label>
content<br>
<textarea v-model="board.content" cols="50" rows="5"></textarea>
</label>
<br><br>
revision count : {{revision}}
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data(){
return {
board:{
title:"Welcome to Vue JS 3!",
content:"VueJS는 사용자 인터페이스를 만들기 위한 progressive framework 입니다."
},
revision:0
};
},
watch:{
// not working
board:function(){
this.revision++;
}
}
});
app.mount("#app");
</script>
</body>
</html>
data에 board
라는 이름의 객체가 존재하며, 객체 안에는 title과 content라는 세부 항목이 존재한다.
data(){
return {
board:{
title:"Welcome to Vue JS 3!",
content:"VueJS는 사용자 인터페이스를 만들기 위한 progressive framework 입니다."
},
revision:0
};
},
입력창은 객체가 아니라 객체 안의 항목인 title
, content
에 연결되어 있다.
<input type="text" v-model="board.title">
<textarea v-model="board.content" cols="50" rows="5"></textarea>
이 경우 객체의 내부 값이 변했다고 해서 객체가 변했다고 할 수 있을까? 그렇지 않다. 사람의 경우도 이름을 바꾼다고 해서 다른 사람이 되지 않듯이 객체도 내부의 값이 변경되었다고 해서 객체가 변화했다고 볼 수 없다. 따라서 일반적인 감시자로는 변화를 감지해낼 수 없다.
사용법
내용물의 변화까지도 감시자로 감지하고 싶은 경우 사용할 수 있는 것이 깊은 감시(deep watch)이다.
깊은 감시는 다음과 같이 객체형태로 설정한다.
watch:{
항목명:{
deep:true,
handler(v, p){
}
}
},
사용 예제 - 깊은 감시 적용
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue deep watch</title>
<style>
* {
box-sizing: border-box;
font-size: 15px;
}
textarea{
resize: none;
padding:0.5em;
}
input{
padding:0.5em;
}
</style>
</head>
<body>
<div id="app">
<label>
title<br>
<input type="text" v-model="board.title">
</label>
<br><br>
<label>
content<br>
<textarea v-model="board.content" cols="50" rows="5"></textarea>
</label>
<br><br>
revision count : {{revision}}
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data(){
return {
board:{
title:"Welcome to Vue JS 3!",
content:"VueJS는 사용자 인터페이스를 만들기 위한 progressive framework 입니다."
},
revision:0
};
},
watch:{
// not working
// board:function(){
// this.revision++;
// },
// deep watch
board:{
deep:true,
handler(){
this.revision++;
}
}
}
});
app.mount("#app");
</script>
</body>
</html>
실행해보면 정상적으로 잘 감시가 되는 것을 확인할 수 있다.
immediate
감시자 객체에 immediate 속성을 설정하면 Vue instance 실행 후 최초 1회는 대상의 변화가 없어도 실행된다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue deep watch</title>
<style>
* {
box-sizing: border-box;
font-size: 15px;
}
textarea{
resize: none;
padding:0.5em;
}
input{
padding:0.5em;
}
</style>
</head>
<body>
<div id="app">
<label>
title<br>
<input type="text" v-model="board.title">
</label>
<br><br>
<label>
content<br>
<textarea v-model="board.content" cols="50" rows="5"></textarea>
</label>
<br><br>
revision count : {{revision}}
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data(){
return {
board:{
title:"Welcome to Vue JS 3!",
content:"VueJS는 사용자 인터페이스를 만들기 위한 progressive framework 입니다."
},
revision:0
};
},
watch:{
// not working
// board:function(){
// this.revision++;
// },
// deep watch
board:{
deep:true,
immediate:true,
handler(){
this.revision++;
}
}
}
});
app.mount("#app");
</script>
</body>
</html>
Last updated