<template> <transition name="dialog-fade" @after-enter="afterEnter" @after-leave="afterLeave"> <div v-show="visible" class="el-dialog__wrapper" @click.self="handleWrapperClick"> <div role="dialog" :key="key" aria-modal="true" :aria-label="title || 'dialog'" :class="['el-dialog', { '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: { title: { type: String, default: '' }, modal: { type: Boolean, default: true }, modalAppendToBody: { type: Boolean, default: true }, appendToBody: { type: Boolean, default: false }, lockScroll: { type: Boolean, default: true }, closeOnClickModal: { type: Boolean, default: true }, closeOnPressEscape: { type: Boolean, default: true }, showClose: { type: Boolean, default: true }, width: String, fullscreen: Boolean, customClass: { type: String, default: '' }, top: { type: String, default: '15vh' }, beforeClose: Function, center: { type: Boolean, default: false }, destroyOnClose: Boolean }, data() { return { closed: false, key: 0 }; }, watch: { 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'); if (this.destroyOnClose) { this.$nextTick(() => { this.key++; }); } } } }, 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.' } }; }, handleWrapperClick() { if (!this.closeOnClickModal) return; this.handleClose(); }, handleClose() { if (typeof this.beforeClose === 'function') { this.beforeClose(this.hide); } else { this.hide(); } }, 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'); }, afterEnter() { this.$emit('opened'); }, afterLeave() { this.$emit('closed'); } }, mounted() { if (this.visible) { this.rendered = true; this.open(); if (this.appendToBody) { document.body.appendChild(this.$el); } } }, 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>