rating-control 컴포넌트를 내장 input처럼 사용할 수 있다면 좋을 것 같다.
여기에 v-model을 사용해서 커스텀 컴포넌트인 rating-control이 내부적으로 가진 값을 TheForms.vue의 데이터 프로퍼티인 rating과 바인딩한다.
<rating-control v-model="rating"></rating-control>
input 요소에 쓰인 v-model은 결국 축약어일 뿐이다.
input 이벤트를 수신하고, value 속성을 바인딩하는 코드의 축약어. 이걸 활용해볼 수 있다.
<input @input="" value="" />
2023.07.03 - [Vue.js] - [Udemy Vue 완벽가이드 Section2] 27. 데이터 바인딩 + 이벤트 바인딩 = 양방향 바인딩
input 이벤트와 value 프로퍼티는 이 input 요소에만 지정되어 있지만,
커스텀 컴포넌트에 v-model을 사용하면 Vue는 해당 컴포넌트에 특정 props를 설정하고, 그 컴포넌트에서 발생(emit)하는 특정 이벤트를 수신하게 된다.
어떤 props이고, 어떤 이벤트일까?
# modelvalue
v-model은 특정 props를 설정한다. 그래서 커스텀 컴포넌트에 해당 props를 선언해줘야한다. → modelValue
//RatingControl.vue
props: ['modelValue']
props에 'modelValue'를 설정해준다.
커스텀 컴포넌트에 v-model을 사용하는 것은 model-value이라는 props를 수동으로 바인딩하는것과 같다.
<rating-control :model-value="rating"></rating-control>
# update:modelvalue
다른 하나는 특수 이벤트를 발생시킨다. → update:modelValue
props: ['modelValue'],
emits: ['update:modelValue']
** 기본적으로 컴포넌트의 v-model은 modelValue를 프로퍼티로, update:modelValue를 이벤트로 사용한다.
v-model에 인자를 전달하여 이러한 이름을 수정할 수 있다.
<rating-control v-model:title="rating"></rating-control>
props: ['title'],
emits: ['update:title'] //props가 title이면 emits은 update:title이어야 한다.
정리하면,
rating-control 커스텀 컴포넌트에 v-model을 사용하는건 model-value props를 수동으로 바인딩하고, update:modelValue 커스텀 이벤트를 수신하는것과 같다.
<rating-control :model-value="rating" @update:modelValue="rating값변경하는 함수.."></rating-control>
RatingControl.vue컴포넌트의 activate 메서드에서 updaet:modelValue를 emit하고, option을 v-model로 전달해보자.
<!--RatingControl.vue-->
<template>
<ul>
<li :class="{ active: activeOption === 'poor' }">
<button type="button" @click="activate('poor')">Poor</button>
</li>
<li :class="{ active: activeOption === 'average' }">
<button type="button" @click="activate('average')">Average</button>
</li>
<li :class="{ active: activeOption === 'great' }">
<button type="button" @click="activate('great')">Great</button>
</li>
</ul>
</template>
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue'],
data() {
return {
activeOption: this.modelValue, //TheForm.vue파일의 data 프로퍼티에 있는 rating초기값.
};
},
methods: {
activate(option) {
this.activeOption = option;
this.$emit('update:modelValue', option);
},
},
};
</script>
TheForm.vue 파일로 돌아가서 console.log로 rating값을 출력해보자.
methods: {
submitForm() {
console.log('Rating');
console.log(this.rating);
this.rating = null;
},
}
Poor, Average, Great 여러 옵션 중에서 선택할 수 있다. "Save Data" 버튼을 눌러 제출하면, 선택한 옵션이 콘솔에 출력되는게 보인다.
# props인 modelValue값을 data 프로퍼티로 지정 시 문제점
하지만 양식 제출 후에 this.rating = null이라는 코드가 있음에도 불구하고 reset이 되지 않는다.
rating을 null로 바꾸는 코드는 작성했지만, 아쉽게도 실제로는 reset이 되지 않는다.
"Save Data"를 한번 더 누르면, rating의 값은 null값이 콘솔에 출력되지만,
시각적 피드백은 여기 rating에 저장된 값과 동기화되지 않는다.
왜 이런 문제가 발생할까?
modelValue props는 activeOption을 초기화하는데만 사용하고, 이후에는 props로 받은 modelValue가 data옵션의 activeOption에 반영되지 않기 때문.
## 해결책
1/ 외부에서 오는 modelValue의 변화에 반응하지 않는 data를 사용하는 대신, computed 프로퍼티를 사용하면 된다.
activeOption을 computed 프로퍼티로 설정할 수 있다.
computed: {
activeOption(){
return this.modelvalue;
}
}
왜 이렇게 할까?
새 옵션을 선택할때마다 'update:modelValue'이벤트를 emit하고 있다.
그리고 이 이벤트는 v-model에 의해 선택되고, 우리가 선택한 옵션은 TheForm컴포넌트(부모컴포넌트)에서 rating-control 컴포넌트와 바인딩된 "rating" 데이터 프로퍼티에 저장된다.
이제 v-model이 작동해서 rating 값을 rating-control 컴포넌트로 돌려보낸다.
따라서 modelValue prop값은 이벤트 update:modelValue를 emit시킬때마다 update된다.
activeOption을 사용하고, this.modelValue를 반환한다.
2/ template에서 activeOption대신 modelValue를 바로 사용해라.
activate 함수에 전달한 값을 modelValue도 가지고 있기 때문에 이렇게 작성해도 작동한다.
activate(option) {
this.$emit('update:modelValue', option);
},
** 즉, props로 넘어온 modelValue값은 변경되는데 data프로퍼티에 초깃값으로 저장된 modelValue는 변경되지 않는다.
참조
https://ko.vuejs.org/guide/components/v-model.html
** 출처: 모든 내용은 Udemy Vue-완벽가이드 강의를 기반으로 작성하였습니다.
'Vue.js' 카테고리의 다른 글
[Udemy Vue 완벽가이드 Section12] 153. 백엔드 추가 (0) | 2023.09.17 |
---|---|
[Udemy Vue 완벽가이드 Section12] 152. 초기 앱 및 백엔드가 필요한 이유 (0) | 2023.09.17 |
[Udemy Vue 완벽가이드 Section11] 147. 커스텀 컨트롤 컴포넌트 구축하기 (0) | 2023.09.14 |
[Udemy Vue 완벽가이드 Section11] 146. 기본 양식 유효성 검사 추가 (0) | 2023.09.14 |
[Udemy Vue 완벽가이드 Section11] 145. 체크박스 및 라디오 버튼과 함께 v-model 사용하기 (0) | 2023.09.13 |