728x90

JavaScript와 HTML, CSS등에 대해서는 일체 다루지 않는다.

기초지식은 다른 강의를 참조하도록 하라.


참고:

[Package]Bower(Front End Pacakage 관리) 설치

[Package]Vue.js


아래와 같은 상황이 있다고 가정해보자.

<!--App.vue-->
<template>
<div id="app">
<Person :name="name"></Person>
<input type="text" v-model="name">
</div>
</template>

<script>
import Person from "./components/Person";

export default {
name: 'App',
components: {Person},
data() {
return {
name: 'Tomato Apple',
}
},
methods:{

}
}
</script>

<style scoped>

</style>
<!--Person.vue-->
<template>
<div class="person">
first name : {{name.split(' ')[0]}}<br>
last name : {{name.split(' ')[1]}}<br>
</div>
</template>

<script>

export default {
name: 'Person',
props: {
name:{}
},
data() {
return {
}
},
created: function () {

},
methods: {},
computed: {}
}
</script>

<style scoped>
.person {
padding: 10px;
background-color: skyblue;
}
</style>

내가 받은 입력을 받아서 앞부분은 이름, 뒷 부분은 성으로 취급하려고 한다고 가정해보자.

그러면 여러분은 위처럼 짤 수 있다.


first name : {{name.split(' ')[0]}}<br>
last name : {{name.split(' ')[1]}}<br>

문제는 이런 코드는 직관성을 꽤 해친다고 할 수 있다.

전혀 직관적이지 않는다.

이래서 여러분은 두가지의 해결책을 제시할 수 있다.


1.메소드를 사용해서 해결합시다.

<!--Person.vue-->
<template>
<div class="person">
first name : {{firstName()}}<br>
last name : {{lastName()}}<br>
</div>
</template>

<script>

export default {
name: 'Person',
props: {
name: {}
},
data() {
return {}
},
created: function () {

},
methods: {
firstName() {
return this.name.split(' ')[0]
},
lastName() {
return this.name.split(' ')[1]
},
},
computed: {}
}
</script>

<style scoped>
.person {
padding: 10px;
background-color: skyblue;
}
</style>

메소드를 이용해서 해결하는 방법이 있다.

하지만 계속 저렇게()를 보는것도 좀 그렇다.



2.data로 위임받아서 해결합시다.

<!--Person.vue-->
<template>
<div class="person">
first name : {{firstName}}<br>
last name : {{lastName}}<br>
</div>
</template>

<script>

export default {
name: 'Person',
props: {
name: {}
},
data() {
return {
firstName: this.name.split(' ')[0],
lastName: this.name.split(' ')[1],
}
},
created: function () {
},
methods: {

},
computed: {}
}
</script>

<style scoped>
.person {
padding: 10px;
background-color: skyblue;
}
</style>

훨씬 깔끔해 진것 같지만 더더욱 치명적인 문제가 있다.


왜냐하면 props가 바뀐다고해서 자식의 data가 바뀌지 않기 때문이다.

methods는 해당 데이터(props, data, computed)가 바뀌면 자동으로 바뀌게 된다.

(이 때 바뀌는 원리는 비효율적이게 돌아간다. 이유는 다음 포스팅에 언급하겠다.)


따라서 이런 문제를 해결?

하기 위해서라기보단 더 정확히 말하면 "이런 문제도 해결할 수 있는" watch라는 녀석이 등장하게 된 것이다.


watch - "난 감시하는 녀석"


<!--Person.vue-->
<template>
<div class="person">
first name : {{firstName}}<br>
last name : {{lastName}}<br>
</div>
</template>

<script>

export default {
name: 'Person',
props: {
name: {}
},
watch: {
name() {
this.firstName = this.name.split(' ')[0];
this.lastName = this.name.split(' ')[1];
}
},
data() {
return {
firstName: this.name.split(' ')[0],
lastName: this.name.split(' ')[1],
}
},
created: function () {
},
methods: {},
computed: {}
}
</script>

<style scoped>
.person {
padding: 10px;
background-color: skyblue;
}
</style>

watch를 선언해주고 안에 변경할 변수의 이름을 적는다.


name() {
this.firstName = this.name.split(' ')[0];
this.lastName = this.name.split(' ')[1];
}

우리는 name의 변경을 감지할 것이므로 name을 적는다.

그러면 이제부터 name이라는 변수에 이벤트리스너가 달렸다고 생각하면된다.

이는 반드시 props일 필요는 없다. data나 computed도 감지하게 된다.


이제 동작하는걸 확인할 수 있다.


하지만 watch의 사용은 잘 권장되지 않는다.

디자인적인 관점에서, 디버깅적인 관점에서 사용할 경우 꽤 힘들어진다.

그래서 보통 watch는 이벤트 리스너로서 사용해야할 때 어쩔수 없이 쓰는 느낌이 강하다.


하지만 뭐... 다 핸들링할 자신있으면 사용해도 큰 무리는 없다는게 필자의 생각이다.

+ Recent posts