Computed
연산 결과를 캐싱해주는 computed 에 대해서 알아보겠습니다.
Copy // App.vue
<template>
<div id="app">
{{ message }}
</div>
</template>
<script>
export default {
name: 'app',
data () {
return {
message: 'Hello Vue !!'
}
}
}
</script>
위 처럼 "Hello Vue !!" 라는 state 값을 뒤집어서 표현하기 위해 아래와 같이 코드를 추가하였습니다.
Copy <template>
<div id="app">
{{ message }}
<h2>뒤집힌 message</h2>
{{ message.split("").reverse().join("") }}
</div>
</template>
위처럼 템플릿 영역에 연산처리를 넣을 수 있습니다. 하지만 state 또는 props 가 변경될 때마다 re-render 되기 때문에 매번 연산을 해야된다는 부담이 있습니다.
이런 부담을 줄이고자 우리는 computed
라는 것을 이용하여 연산결과를 캐싱
하여 사용할 수 있습니다.
Copy <template>
<div id="app">
{{ message }}
<h2>뒤집힌 message</h2>
{{ reversedMessage }}
</div>
</template>
<script>
export default {
name: 'app',
data () {
return {
message: 'Hello Vue !!'
}
},
computed: {
reversedMessage () {
return this.message.split("").reverse().join("")
}
}
}
</script>
computed 는 대상(ex. message) 을 따라 연산결과가 캐싱됩니다. 대상인 message 가 변경되지 않는다면 이미 연산처리된 즉, 캐싱처리되어있는 reversedMessage 를 가져옵니다.
Method 에서도 같은 역할을 할 수 있지 않나요 ?
물론 가능합니다. 결과는 같습니다. 하지만 함수의 경우는 re-render 될 때마다 실행되기 때문에 캐싱 이득을 취할 수 없습니다.
Copy methods: {
reversedMessage2 () {
return this.message.split("").reverse().join("")
}
}
Watch
state 나 props 를 감시하고 해당 값이 변경 되었을 때의 행동을 지정할 수 있는 watch 라는 속성에 대해서 알아보겠습니다.
fistname, lastname 을 적을 수 있는 input 을 준비하고 입력된 값을 합쳐 full name 을 출력하고 싶습니다.
Copy <template>
<div id="app">
<input v-model="firstname" />
<input v-model="lastname"/>
<h2>full name</h2>
<span></span>
</div>
</template>
<script>
export default {
name: 'app',
data () {
return {
firstname: '',
lastname: ''
}
}
}
</script>
먼저 watch
를 이용하여 출력해보겠습니다.
Copy export default {
name: 'app',
data () {
return {
firstname: '',
lastname: ''
}
},
watch: {
firstname (val) {
console.log('fistname', val)
},
lastname (val) {
console.log('lastname', val)
}
}
}
watch 할 대상을 적어주고 대상의 값이 변경되었을 때의 행동을 적어줍니다.
fullname 이라는 state 값을 추가하고 watch 의 값이 바뀔 때마다 fullname 의 값을 변경하도록 하였습니다.
Copy <template>
<div id="app">
<input v-model="firstname" />
<input v-model="lastname"/>
<h2>full name</h2>
<span>{{ fullname }}</span>
</div>
</template>
<script>
export default {
name: 'app',
data () {
return {
firstname: '',
lastname: '',
fullname: ''
}
},
watch: {
firstname (val) {
this.fullname = `${val} ${this.lastname}`
},
lastname (val) {
this.fullname = `${this.firstname} ${val}`
}
}
}
</script>
하지만 위같은 처리를 하기위해 watch 는 좋은방법이 아닙니다. computed 라는 더 좋은 친구가 있기 때문입니다.
watch 를 computed 로 변경하기
watch 로 fullname 을 만들기 위해서는 2개의 state (first, last name) 에 watch 를 해야했습니다. 하지만 아래와 같이 computed 를 이용하면 watch 를 할필요없이 대상을 바라보게 하는 것 만으로도 fullname 을 만들 수 있습니다.
fullname 이라는 state 도 필요없어집니다. 훨씬 더 보기 편하지 않나요 ? 관리 측면에서도 훨씬 좋습니다.
Copy <template>
<div id="app">
<input v-model="firstname" />
<input v-model="lastname"/>
<h2>full name</h2>
<span>{{ fullname }}</span>
</div>
</template>
<script>
export default {
name: 'app',
data () {
return {
firstname: '',
lastname: '',
}
},
computed: {
fullname () {
return `${this.firstname} ${this.lastname}`
}
}
}
</script>
watch ?.. computed ..?
두 가지 모두 같은 결과를 내는데 그러면 어떤걸 쓰면 좋은건가요 ..? watch 는 언제 변하는지 예측이 어려울때 많이 사용됩니다. 예를 들어 비동기 통신이 있습니다. 우리가 어떤 데이터를 요청했을 때 이 값이 1초뒤에 올지 2초뒤에 올지 예측이 어려울때 그 값을 watch 를 통하여 감시하고 있다가 해당 값에 대한 응답이 왔을때 후처리를 해줄 수 있습니다.
computed 는 위에서 알아본 것처럼 복잡한 연산같은 것을 캐싱처리하기 위해 사용됩니다.
각각의 용도가 있기 때문에 잘 나누어 사용하는것이 중요합니다 :)