프로젝트 진행 중이라 개인 공부가 더뎌지고 있어서 개발하면서 기록 남길겸 작성해본다,
Dropdown 기본구조
<div class="dropdown" :class="{ 'is-open': isOpen }" @click="onStopPropagation">
<div v-if="isHasSlotText" class="label">
<slot />
</div>
<div class="dropdown-wrap">
<button
class="dropdown-btn"
type="button"
:style="{
width: `${width}rem`
}"
@click="onToggleMenu"
>
{{ selectedLabel || defaultText }}
</button>
<div class="dropdown-icon">
<i class="ic-expand-more" />
</div>
<div v-if="isOpen && optionList && optionList[0]" class="dropdown-menu">
<button v-for="item in optionList" :key="item.value" type="button" @click="onSelected(item)">
{{ item.label }}
</button>
</div>
</div>
</div>
<script>
export default {
name: 'SDropdown',
props: {
value: {
type: [String, Number, Boolean, null],
required: false,
default: null
},
// optionList: [{ value: '', label: '' }]
optionList: {
type: Array,
required: false,
default: () => []
},
defaultText: {
type: String,
required: false,
default: '옵션선택'
},
// value: x-small | small | normal | large
wSize: {
type: String,
required: false,
default: 'normal'
}
},
data() {
return {
width: 15.2,
isOpen: false
};
},
computed: {
isHasSlotText() {
return !!this.$slots.default;
},
selectedLabel() {
const targetValue = this.value;
const isHasNullValue = !!this.optionList.find((item) => item.value === null);
const targetOption = this.optionList.find((item) => item.value === targetValue);
return isHasNullValue || (targetValue != null && targetOption) ? targetOption.label : null;
}
},
created() {
let width = 15.2;
switch (this.wSize) {
case 'x-small':
width = 9.5;
break;
case 'small':
width = 12.2;
break;
case 'normal':
width = 15.2;
break;
default:
width = 20;
break;
}
this.width = width;
},
mounted() {
document.addEventListener('click', () => {
this.isOpen = false;
});
},
methods: {
onStopPropagation(e) {
e.stopPropagation();
},
onToggleMenu() {
this.isOpen = !this.isOpen;
},
onSelected({ value }) {
this.isOpen = false;
this.$emit('input', value);
this.$emit('change');
}
}
};
</script>
optionList를 computed hallOptionList로 연결하여 내려줌
store에 hallList를 전역으로 설정한 후 받아와 map 함수를 이용하여 value와 label에 넣어주며, unshift를 활용하여 전체 값도 추가한다.
<Dropdown v-model="queryOptions.hall" :option-list="hallOptionList">홀:</SDropdown>
<script>
computed: {
hallOptionList() {
const hallList = this.$store.state.HALL_LIST.map((hall) => ({
value: hall,
label: `${hall} 홀`
}));
hallList.unshift({ value: null, label: '전체' });
return hallList;
}
},
</script>
기본구조
<template>
<transition name="fade">
<div v-if="isShow" class="modal-wrap">
<div class="modal-inner">
<div class="modal">
<div class="head">
<button type="button" class="close-btn" @click="$emit('close')">
<i class="ic-close" />
</button>
</div>
<div class="body">
<div class="contents-info mb-24">
<div class="representative-img mr-16">
<img src="" alt="" />
</div>
<div class="works-info">
<p class="mt-1m">{{ docentData.title }}</p>
<p class="mt-2r">{{ docentData.writer }}</p>
<p class="mt-2r">{{ docentData.position }}</p>
<div>
<audio class="player" controls></audio>
</div>
</div>
</div>
<div>
<p>
{{ docentData.intro }}
</p>
</div>
</div>
<div class="foot">
<div class="map-img">
<img src="" alt="" />
</div>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
import { disableBodyScroll, clearAllBodyScrollLocks } from 'body-scroll-lock';
export default {
name: 'DocentModal',
props: {
isShow: {
type: Boolean,
required: false,
default: false
},
docentData: {
type: Object,
required: false,
default: () => null
}
},
data() {
return {};
},
watch: {
isShow(newValue) {
if (newValue) {
disableBodyScroll(document);
} else {
clearAllBodyScrollLocks();
}
}
},
beforeDestroy() {
clearAllBodyScrollLocks();
}
};
</script>
리스트 클릭 시 Modal이 나오며 index에 따른 data를 넣어줘야한다,
그래서 리스트를 클릭 시 index를 넣어주고 computed로 index를 담을 변수를 선언 후
return 하여 data에 해당 index를 넣어준다.
<tr v-for="(item, index) in data" :key="item.id" @click="openDocentModal(index)">
<td>
<div>{{ docentData.startCount + index }}</div>
</td>
</tr>
<script>
data() {
return {
docentData: null,
modal: {
isDocent: false
},
selectedDocentIndex: null,
};
},
computed: {
selectedDocentData() {
const selectedDocentIndex = this.selectedDocentIndex;
return selectedDocentIndex != null ? this.docentData.content[selectedDocentIndex] : null;
}
},
methods: {
openDocentModal(index) {
this.selectedDocentIndex = index;
this.modal.isDocent = true;
},
}
</script>