[Vue] computed property 값 변경하기
화면에서 computed
속성의 값을 변경 시킬 경우 발생하는 오류와 이에 대한 해결 방법을 이야기하고자 한다.
먼저, 아래의 소스를 보자.
<template>
<div>
<p>computed 값: {{ compDefaultValue }}</p>
<button @click="increase">문구 변경</button>
</div>
</template>
<script>
export default {
data: () => ({
defaultValue: 0
}),
computed: {
compDefaultValue() {
return this.defaultValue
}
},
methods: {
increase() {
this.compDefaultValue = 1
}
}
}
</script>
위 소스에서 문구 변경을 클릭할 경우 호출되는 increase
함수에서 this.compDefaultValue = 1
을 하는 순간 아래와 같은 오류가 발생할 것이다.
vue.runtime.esm.js:619 [Vue warn]: Computed property "compDefaultValue" was assigned to but it has no setter.
computed
내 에서 사용되는 속성들은 단어그대로 계산된 속성 (computed properties) 이 정의되는 것인데
이는 명시적으로 값을 설정하지 않는 읽기 전용
으로 설계되어 있다.
이렇게 읽기 전용
으로 설계 된 속성을 변경하려하면 위와 같은 오류가 발생하게 된다.
만약 값을 수정해야 할 필요가 있을때는 get()
및 set()
메소드를 사용하면 된다.
get()
정의 된 값을 반환한다. getter 라고 표현한다.
set()
정의 된 값을 수정한다. setter 라고 표현한다.
getter, setter 를 사용하여 수정된 소스는 아래와 같다.
<template>
<div>
<p>computed 값: {{ compDefaultValue }}</p>
<button @click="increase()">값 증가</button>
</div>
</template>
<script>
export default {
data: () => ({
defaultValue: 0
}),
computed: {
compDefaultValue: {
get() {
return this.defaultValue
},
set(newValue) {
this.defaultValue = this.defaultValue + newValue
}
}
},
methods: {
increase() {
this.compDefaultValue = 1
}
}
}
</script>
이제 값 증가 버튼을 클릭하면 setter (set()) 를 통해 전달된 1 값이 기존 defaultValue 값에 더해지고,
화면에는 getter (get()) 를 통해 자동으로 업데이트 된 값이 표시된다.
여기서 한가지 체크할 부분은.. 사실 아래와 같이 increase
함수에서 defaultValue 값 자체를 증가시키면 좀 더 간단하게 해결이 된다.
<template>
<div>
<p>computed 값: {{ compDefaultValue }}</p>
<button @click="increase">값 증가</button>
</div>
</template>
<script>
export default {
data: () => ({
defaultValue: 0
}),
computed: {
compDefaultValue() {
return this.defaultValue
}
},
methods: {
increase() {
this.defaultValue = this.defaultValue + 1
}
}
}
</script>
하지만 getter, setter 가 필요한 경우가 있는데 예를들면 체크박스를 사용할 때와 같은 경우이다.
아래의 예제는 vuex
를 사용 시 store
내 state
의 변수값을 이용하여 체크박스를 사용하는 예제이다.
(v-checkbox 는 vuetify2 (https://vuetifyjs.com)에서 사용되는 요소 선언이다.)
...store: main.js
export default {
namespace: true,
state: {
checkAll: false
}
...
}
...template: main.vue
<template>
<div>
<v-checkbox
v-model="checkAll"
:label="`value: ${checkAll}`"
></v-checkbox>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
computed: {
...mapState('main', {
checkAll: state => state.checkAll
})
}
}
</script>
위와 같이 작성하였을 경우 본문에서 언급한 setter 오류가 동일하게 발생한다.
이때 간단하게 해결 할 수 있는 방법이 getter, setter 를 이용한 방법이다.
수정 된 코드는 아래와 같다.
store: main.js
export default {
namespace: true,
state: {
checkAll: false
}
...
mutations: {
setCheckAll(state, v) {
state.checkAll = v
}
}
}
template: main.vue
<template>
<div>
<v-checkbox
v-model="compCheckAll"
:label="`value: ${compCheckAll}`"
></v-checkbox>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
computed: {
...mapState('main', {
checkAll: state => state.checkAll
}),
compCheckAll: {
get() {
return this.checkAll
},
set(v) {
this.$store.commit('main/setCheckAll', v)
}
}
}
}
</script>
이렇게 하면 checkbox 를 클릭 할 때마다 store
의 mutations
에 설정 된 setCheckAll
함수가 호출되며
이때 변경 된 값을 전달하게 되고, 그 값은 바로바로 화면에 표시 될 것이다.