Modal
Modal (모달 대화상자)
현재 화면 위에 뜨는 모달 대화상자 컴포넌트예요.
출처: 문서
본문
언제 사용하나요
-
사용자가 무언가를 처리해야 하지만 페이지를 이동해 작업 흐름을 끊고 싶지 않을 때, Modal을 사용해 현재 화면 한가운데에 레이어를 띄우고 해당 작업을 진행할 수 있어요.
-
Modal은 사용자와 상호작용하는 역할을 해요. 사용자는 Modal 안에서 정보를 입력하거나 안내를 읽고, 옵션을 설정하는 등의 작업을 할 수 있어요.
기본 사용법
:::demo v-model 양방향 바인딩으로 Modal 표시 여부를 제어하고, title 속성으로 Modal 제목을 설정해요.
<template>
<d-button @click="handleClick">打开 modal</d-button>
<d-modal v-model="visible" title="Start Snapshot Version">
<div>name: {{ data.name }}</div>
<div>age: {{ data.age }}</div>
<div>address: {{ data.address }}</div>
</d-modal>
</template>
<script>
import { defineComponent, ref, reactive } from 'vue';
export default defineComponent({
setup() {
const visible = ref(false);
const data = reactive({
name: 'Tom',
age: 20,
address: 'Chengdu',
});
const handleClick = () => {
visible.value = true;
};
return { visible, data, handleClick };
},
});
</script>
:::
마지막 닫힘 위치 유지
:::demo keep-last를 사용하면 modal을 다시 열 때 마지막에 닫았던 위치가 그대로 유지돼요.
<template>
<d-button @click="handleClick">打开 modal</d-button>
<d-modal v-model="visible" title="Start Keep Last" :keep-last="true">
<div>name: {{ data.name }}</div>
<div>age: {{ data.age }}</div>
<div>address: {{ data.address }}</div>
</d-modal>
</template>
<script>
import { defineComponent, ref, reactive } from 'vue';
export default defineComponent({
setup() {
const visible = ref(false);
const data = reactive({
name: 'Tom',
age: 20,
address: 'Chengdu',
});
const handleClick = () => {
visible.value = true;
};
return { visible, data, handleClick };
},
});
</script>
:::
제목과 동작 버튼 커스터마이즈
:::demo header 슬롯으로 Modal 상단 영역을 커스터마이즈할 수 있어요. 하위 컴포넌트 d-modal-header가 상단 영역에 기본 스타일을 제공하며, 하위 컴포넌트에 style/class를 지정해 스타일을 바꿀 수 있어요. footer 슬롯도 마찬가지예요.
<template>
<d-button @click="handleClick">打开 modal</d-button>
<d-modal v-model="visible">
<template #header>
<d-modal-header>
<d-icon name="like"></d-icon>
<span>Good Title</span>
</d-modal-header>
</template>
<div>name: {{ data.name }}</div>
<div>age: {{ data.age }}</div>
<div>address: {{ data.address }}</div>
<template #footer>
<d-modal-footer style="text-align: right; padding-right: 20px;">
<d-button @click="hidden">取消</d-button>
<d-button @click="hidden">确认</d-button>
</d-modal-footer>
</template>
</d-modal>
</template>
<script>
import { ref, defineComponent, reactive } from 'vue';
export default defineComponent({
setup() {
const visible = ref(false);
const data = reactive({
name: 'Tom',
age: 20,
address: 'Chengdu',
});
const handleClick = () => {
visible.value = true;
};
const hidden = () => {
visible.value = false;
};
return { visible, data, handleClick, hidden };
},
});
</script>
:::
정보 알림
:::demo 여러 타입의 정보 알림 모달이에요.
<template>
<d-button class="mr-1" @click="handleClick('success')">success</d-button>
<d-button class="mr-1" @click="handleClick('failed')">failed</d-button>
<d-button class="mr-1" @click="handleClick('warning')">warning</d-button>
<d-button class="mr-1" @click="handleClick('info')">info</d-button>
<d-modal v-model="visible" title="Start Snapshot Version" :type="type">
<div>name: {{ data.name }}</div>
<div>age: {{ data.age }}</div>
<div>address: {{ data.address }}</div>
</d-modal>
</template>
<script>
import { defineComponent, ref, reactive } from 'vue';
export default defineComponent({
setup() {
const visible = ref(false);
const type = ref('');
const data = reactive({
name: 'Tom',
age: 20,
address: 'Chengdu',
});
const handleClick = (t) => {
visible.value = true;
type.value = t;
};
return { visible, data, handleClick, type };
},
});
</script>
:::
닫기 전 콜백
:::demo 사용자가 닫기 버튼이나 오버레이를 클릭하면 before-close가 호출돼요. 비동기 작업을 마친 뒤 done 파라미터로 Modal을 닫을 수 있어요. close는 Modal이 닫힐 때 발생해요.
<template>
<d-button @click="handleClick">打开 modal</d-button>
<d-modal v-model="visible" :before-close="beforeClose" @close="handleClose" style="width: 500px;">
<div>name: {{ data.name }}</div>
<div>age: {{ data.age }}</div>
<div>address: {{ data.address }}</div>
<template #footer>
<d-modal-footer style="text-align: right; padding-right: 20px;">
<d-button @click="hidden">取消</d-button>
<d-button @click="hidden">确认</d-button>
</d-modal-footer>
</template>
</d-modal>
</template>
<script>
import { ref, defineComponent, reactive } from 'vue';
export default defineComponent({
setup() {
const visible = ref(false);
const data = reactive({
name: 'Tom',
age: 20,
address: 'Chengdu',
});
const handleClick = () => {
visible.value = true;
};
const hidden = () => {
visible.value = false;
};
const beforeClose = (done) => {
new Promise((resolve) => {
setTimeout(resolve, 1000);
}).then(done);
};
const handleClose = () => {
console.log("Modal关闭")
}
return { visible, data, handleClick, hidden, beforeClose, handleClose };
},
});
</script>
:::
모달 안 버튼에 autofocus로 자동 포커스 주기
::: demo button에 autofocus를 설정하면 자동으로 포커스를 받고, enter 키로 버튼 클릭을 트리거할 수 있어요.
<template>
<d-button @click="handleClick">打开 modal</d-button>
<d-modal v-model="visible" title="Start Snapshot Version">
<div>name: {{ data.name }}</div>
<div>age: {{ data.age }}</div>
<div>address: {{ data.address }}</div>
<template #footer>
<d-modal-footer style="text-align: right; padding-right: 20px;">
<d-button @click="hidden" autofocus>取消</d-button>
<d-button @click="hidden">确认</d-button>
</d-modal-footer>
</template>
</d-modal>
</template>
<script>
import { defineComponent, ref, reactive } from 'vue';
export default defineComponent({
setup() {
const visible = ref(false);
const data = reactive({
name: 'Tom',
age: 20,
address: 'Chengdu',
});
const handleClick = () => {
visible.value = true;
};
const hidden = () => {
visible.value = false;
};
return { visible, data, handleClick, hidden };
},
});
</script>
:::
Modal 파라미터
| 파라미터 | 타입 | 기본값 | 설명 | Demo 링크 |
|---|---|---|---|---|
| v-model | boolean |
false | Modal 표시 여부 | 기본 사용법 |
| title | string |
- | 선택, Modal 제목 | 기본 사용법 |
| keep-last | boolean |
false | 선택, 이전 이동 위치 유지 여부 | 마지막 닫힘 위치 유지 |
| lock-scroll | boolean |
true | 선택, body 스크롤 잠금 여부 | |
| close-on-click-overlay | boolean |
true | 선택, 빈 곳 클릭으로 Modal 닫기 가능 여부 | |
| before-close | (done) => void |
- | 선택, 닫기 전 콜백. done을 호출하면 Modal 닫기 가능 | 닫기 전 콜백 |
| escapable | boolean |
true | 선택, esc 키로 팝업 닫기 지원 여부 | |
| show-close | boolean |
true | 선택, 닫기 버튼 표시 여부 | |
| draggable | boolean |
true | 선택, 다이얼로그 드래그 가능 여부 | |
| show-animation | boolean |
true | 선택, 애니메이션 표시 여부 | |
| show-overlay | boolean |
true | 선택, 오버레이 레이어 표시 여부 | |
| append-to-body | boolean |
true | 선택, Modal을 body 레이어로 승격 여부 | |
| type | success | failed | warning | info | - | 선택, 다이얼로그 힌트 메시지 |
Modal 이벤트
| 이벤트명 | 타입 | 설명 |
|---|---|---|
| close | - |
Modal 닫힐 때 트리거 |
Modal 슬롯
| 슬롯명 | 설명 |
|---|---|
| default | Modal 콘텐츠 |
| header | Modal 상단 커스텀. title과 header를 함께 사용하면 header 우선 렌더링 |
| footer | Modal 하단 커스텀 |
더 알아보기 (Learn more)
before-close 콜백과 header/footer 슬롯을 활용하면 실제 서비스에 필요한 모달을 쉽게 만들 수 있어요.