일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- awss3
- 시스템설계면접팁
- react
- 가상면접으로대규모시스템
- 테스트코드책
- 디자인패턴
- 시스템설계면접
- 리액트구글애널리틱스
- formik react-query submitting not working
- 시스템설계
- cypress React
- 시스템설계방법
- cypressBDD
- git commit merge
- FirebaseAnalytics
- 가상면접2장
- 가상면접3장
- 리팩토링2판4장
- Git commit 합치기
- 전략패턴
- react-ga
- 시스템설계면접예시
- 리팩터링2판테스트
- formik submitting not working
- file not found Error
- gitsquash
- s3이미지다운로드됨
- git commit 협업
- git squash
- 헤드퍼스트전략패턴
- Today
- Total
mingg IT
[Vue] Vue3+typescript 공통 컴포넌트 만드는 방법 본문
보통 우리가 부모컴포넌트에서 자식컴포넌트로 데이터를 넘겨주고, 변경하기 위해선 props 와 emit을 주로 사용한다.
공통 컴포넌트를 만들면서 props로 전달받은 값을 직접 변경할 수 없기 때문에 Object로 통째로 넘겨주거나(v-model을 사용하기 위해) 혹은 emit을 이용해서 결국 부모컴포넌트에서 emit을 이용해 받아온 값으로 수정을 해주었다.
쓰면서 너무 불편했고 공통 컴포넌트가 맞나 생각이 들던 와중에 새로운 방법을 발견했다.
container.vue (부모컴포넌트임)
<template>
<List
v-model:time="dummy.time"
v-model:duration="dummy.duration"
/>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
interface containerType {
time : string;
duration: number;
}
export default defineComponent({
name: 'container',
setup() {
const dummy = ref<containerType>({time: 'DAY', duration:1});
return {dummy}
}
})
</script>
List라는 공통 컴포넌트를 만들고 여러군데에서 사용한다고 가정하자.
보통 우리가 props를 넘겨줄땐 :time="dummy.time" 을 사용한다.
허나 v-model:time="dummy.time"으로 넘겨준 것을 확인할 수 있다.
이렇게 v-model:{props이름} 을 통째로 넘겨주면 vue 내부에서 emit을 만든다고 한다.
그러면 공통컴포넌트인 List에선 어떻게 사용해주면 될까?
List.vue (공통 컴포넌트)
<template>
<div class="form-group mr-1 ml-1">
<label for="timeLabel">시간 단위</label>
<select :value="time" @change="changeData($event, 'time')" class="custom-select" id="timeLabel" style='width: 100px'>
<option v-for="(day, index) in repeatTimeList" :key="index">
{{day}}
</option>
</select>
</div>
<div class="form-group mr-3">
<label for="durationLabel">기간</label>
<input :value="duration" @change="changeData($event, 'duration')" type="number" class="form-control form-control-sm repeat_input_form" id="durationLabel" placeholder="초기화 전체 기간을 입력하세요">
</div>
</template>
<script lang="ts">
import { defineComponent, PropType, ref, toRefs } from 'vue'
import { Time } from '@/models/store'
export default defineComponent({
name: 'List',
props: {
time: String as PropType<Time>,
duration: Number as PropType<number>,
},
emits: ['update:time', 'update:duration'],
setup(props, { emit }) {
const repeatTimeList = ref<Time[]>(['DAY', 'MONTH']);
function changeData(event: Event, target: string) {
switch(target) {
case 'time':
emit('update:time', (event.target as HTMLSelectElement).value);
break;
case 'duration':
emit('update:duration', (event.target as HTMLSelectElement).value);
break;
}
}
return { repeatTimeList, setRepeatData }
}
})
</script>
<style lang="scss" scoped>
.repeat_input_form {
min-height: 35px;
}
</style>
보면 emits로 ['update:{props이름}] 설정해주고, 전달받은 props들을 :value로 보여준다.
변경같은경우에는 @change 이벤트를 이용하여 emit을 불러와주면 된다.
이러면 부모컴포넌트에서 emit과 관련된 부분을 전혀 신경쓸 필요없이 List(공통컴포넌트)에서 데이터의 변경을 관리할 수 있다.
드디어 진정한 공통 컴포넌트의 의미를 가지게 된것 같다.
기회가되면 저렇게 사용하지 않고 기존 방식대로 부모컴포넌트에서 emit을 썼을 경우를 보여주며 비교 하겠음.
혹시 'update:{props이름}' 인데 props를 object로 넘길수도 있는지 아는사람 알려주면 감사하겠다.. props로 object덩어리만 넘기게.. 너무많아서 ..
(부족한 부분 있으면 댓글 남겨주시면 감사하겠습니다.)