vue3:modal元件開發
阿新 • • 發佈:2020-10-28
專案環境
@vue/cli 4.5.8
最終效果
需求分析
顯示/隱藏
點選遮罩層能否關閉
寬度和zIndex自定義
標題欄 -顯示標題和關閉按鈕
主體
底部 -內建取消和確定功能
實現過程
搭建大體的html模版
<template> <teleport to="body"> <div class="modal"> <div class="modal-mask"></div> <div class="modal-content"> <div class="modal-header"> <slot name="header"></slot> </div> <div class="modal-body"> <slot></slot> </div> <div class="modal-footer" v-if="!footerHide"> <slot name="footer"> <button class="modal-button">取消</button> <button class="modal-button modal-button-primary">確定</button> </slot> </div> <div class="modal-close"></div> </div> </div> </teleport> </template> <script lang="ts"> import { defineComponent } from "vue"; export default defineComponent({ name: "Modal", props: {}, emits: [], setup() { return { }; }, }); </script> <style lang="scss"> </style>
新增props和mehtods和css
<template> <teleport to="body"> <div class="modal" v-show="modelValue" :style="{ zIndex: zIndex }"> <div class="modal-mask" @click="maskClose"></div> <div class="modal-content" :style="{ width: width }"> <div class="modal-header"> <slot name="header">{{ title }}</slot> </div> <div class="modal-body"> <slot></slot> </div> <div class="modal-footer" v-if="!footerHide"> <slot name="footer"> <button class="modal-button" @click="closeModal('cancel')">取消</button> <button class="modal-button modal-button-primary" @click="sure">確定</button> </slot> </div> <div class="modal-close" @click="closeModal('close')"></div> </div> </div> </teleport> </template> <script lang="ts"> import { defineComponent } from "vue"; export default defineComponent({ name: "Modal", props: { modelValue: Boolean, title: String, footerHide: Boolean, width: { type: String, default: "500px", }, maskClosable: { type: Boolean, default: true, }, zIndex: { type: Number, default: 1000, }, }, emits: ["ok", "close", "update:modelValue"], // 方便TS推斷 setup(props, { emit }) { const closeModal = (type: string) => { // 關閉Modal 並觸發自定義事件‘close-有引數方便區分點選右上方的關閉按鈕還是點選底部的取消’ }; const maskClose = () => { // 通過點選mask層關閉Modal }; const sure = () => { // 點選確定按鈕關閉Modal並新增自定義事件‘ok’ }; return { closeModal, sure, maskClose }; }, }); </script> <style lang="scss"> .modal { position: fixed; top: 0; left: 0; z-index: 1000; &-mask { width: 100vw; height: 100vh; background-color: rgba($color: #000000, $alpha: 0.4); } &-content { width: 500px; position: absolute; top: 8vh; left: 50%; margin-left: -250px; background-color: #fff; border-radius: 8px; z-index: 1; font-size: 14px; } &-header { padding: 12px 16px; border-bottom: 1px solid #e4e7ed; } &-footer { padding: 12px 16px; border-top: 1px solid #e4e7ed; text-align: right; } &-body { padding: 16px; } &-close { position: absolute; top: 12px; right: 12px; width: 16px; height: 16px; cursor: pointer; &::before, &::after { content: ""; display: block; position: absolute; left: 8px; top: 0; width: 1px; height: 16px; background-color: #999; border-radius: 0.5px; transform: rotate(-45deg); z-index: -1; } &::before { transform: rotate(45deg); } &:hover::before, &:hover::after { background-color: #444; } } &-button { line-height: 1em; font-size: 14px; padding: 8px 20px; border: 1px solid #dcdfe6; outline: none; display: inline-block; border-radius: 4px; cursor: pointer; background-color: #fff; transition: 0.1s; &:hover { color: #409eff; border-color: #c6e2ff; background-color: #ecf5ff; } & + & { margin-left: 10px; } &-primary { background-color: #2d8cf0; border-color: #2d8cf0; color: white; &:hover { background: #66b1ff; border-color: #66b1ff; color: #fff; } } } } </style>
新增closeModal, sure, maskClose的具體實現--setup具體的實現
... setup(props, { emit }) { const closeModal = (type: string) => { emit("update:modelValue", false); emit("close", type); }; const maskClose = () => { if (props.maskClosable) closeModal("close"); }; const sure = () => { emit("update:modelValue", false); emit("ok"); }; return { closeModal, sure, maskClose }; }, ...
完整的程式碼在github