<template> <transition name="dialog-fade" @after-enter="afterEnter" @after-leave="afterLeave"> <div class="el-dialog__wrapper" v-show="visible" @click.self="handleWrapperClick"> <div role="dialog" aria-modal="true" :aria-label="title || 'dialog'" class="el-dialog" :class="[{ 'is-fullscreen': fullscreen, 'el-dialog--center': center }, customClass]" ref="dialog" :style="style"> <div class="el-dialog__header"> <slot name="title"> <span class="el-dialog__title">{{ title }}</span> </slot> <button type="button" class="el-dialog__headerbtn" aria-label="Close" v-if="showClose" @click="handleClose"> <i class="el-dialog__close el-icon el-icon-close"></i> </button> </div> <div class="el-dialog__body" v-if="rendered"><slot></slot></div> <div class="el-dialog__footer" v-if="$slots.footer"> <slot name="footer"></slot> </div> </div> </div> </transition> </template> <script> import Popup from 'element-ui/src/utils/popup'; import Migrating from 'element-ui/src/mixins/migrating'; import emitter from 'element-ui/src/mixins/emitter'; export default { name: 'ElDialog', mixins: [Popup, emitter, Migrating], props: { // Dialog 的标题,也可通过具名 slot (见下表)传入 title: { type: String, default: '' }, // modal 是否需要遮罩层 modal: { type: Boolean, default: true }, // 遮罩层是否插入至 body 元素上,若为 false,则遮罩层会插入至 Dialog 的父元素上 modalAppendToBody: { type: Boolean, default: true }, // Dialog 自身是否插入至 body 元素上。嵌套的 Dialog 必须指定该属性并赋值为 true appendToBody: { type: Boolean, default: false }, // lock-scroll 是否在 Dialog 出现时将 body 滚动锁定 lockScroll: { type: Boolean, default: true }, // close-on-click-modal 是否可以通过点击 modal 关闭 Dialog closeOnClickModal: { type: Boolean, default: true }, // close-on-press-escape 是否可以通过按下 ESC 关闭 Dialog closeOnPressEscape: { type: Boolean, default: true }, // show-close 是否显示关闭按钮 showClose: { type: Boolean, default: true }, // width Dialog 的宽度 String, // fullscreen 是否为全屏 Dialog fullscreen: Boolean, // custom-class Dialog 的自定义类名 customClass: { type: String, default: '' }, // top Dialog CSS 中的 margin-top 值 top: { type: String, default: '15vh' }, // before-close 关闭前的回调,会暂停 Dialog 的关闭 beforeClose: Function, // center 是否对头部和底部采用居中布局 center: { type: Boolean, default: false } }, data() { return { closed: false }; }, watch: { // 是否显示 Dialog,支持 .sync 修饰符 visible(val) { if (val) { this.closed = false; this.$emit('open'); this.$el.addEventListener('scroll', this.updatePopper); this.$nextTick(() => { this.$refs.dialog.scrollTop = 0; }); if (this.appendToBody) { document.body.appendChild(this.$el); } } else { this.$el.removeEventListener('scroll', this.updatePopper); if (!this.closed) this.$emit('close'); } } }, computed: { style() { let style = {}; if (!this.fullscreen) { style.marginTop = this.top; if (this.width) { style.width = this.width; } } return style; } }, methods: { // 暂时没发现这个什么用 getMigratingConfig() { return { props: { 'size': 'size is removed.' } }; }, // 点击dialog自身 handleWrapperClick() { if (!this.closeOnClickModal) return; this.handleClose(); }, // 关闭dialog handleClose() { // 如果有beforeClose,执行beforeClose if (typeof this.beforeClose === 'function') { this.beforeClose(this.hide); } else { // 否则隐藏 this.hide(); } }, // 隐藏dialog hide(cancel) { if (cancel !== false) { this.$emit('update:visible', false); this.$emit('close'); this.closed = true; } }, updatePopper() { this.broadcast('ElSelectDropdown', 'updatePopper'); this.broadcast('ElDropdownMenu', 'updatePopper'); }, // Dialog 打开动画结束时的回调 afterEnter() { this.$emit('opened'); }, // Dialog 关闭动画结束时的回调 afterLeave() { this.$emit('closed'); } }, mounted() { if (this.visible) { this.rendered = true; this.open(); if (this.appendToBody) { document.body.appendChild(this.$el); } } }, // 销毁前移除dom destroyed() { // if appendToBody is true, remove DOM node after destroy if (this.appendToBody && this.$el && this.$el.parentNode) { this.$el.parentNode.removeChild(this.$el); } } }; </script>