iview/components/modal/modal.vue

205 lines
6.4 KiB
Vue
Raw Normal View History

<template>
<div :class="wrapClasses">
<div :class="maskClasses" v-show="visible" @click="mask" transition="fade"></div>
<div :class="classes" :style="styles" v-show="visible" transition="ease">
<div :class="[`${prefixCls}-content`]">
<a :class="[`${prefixCls}-close`]" v-if="closable" @click="close">
<slot name="close">
<Icon type="ios-close-empty"></Icon>
</slot>
</a>
<div :class="[`${prefixCls}-header`]" v-if="showHead" v-el:head><slot name="header"><p>{{ title }}</p></slot></div>
<div :class="[`${prefixCls}-body`]"><slot></slot></div>
<div :class="[`${prefixCls}-footer`]" v-if="!footerHide">
<slot name="footer">
<Button type="ghost" size="large" @click="cancel">{{ cancelText }}</Button>
<Button type="primary" size="large" :loading="buttonLoading" @click="ok">{{ okText }}</Button>
</slot>
</div>
</div>
</div>
</div>
</template>
<script>
import Icon from '../icon';
import Button from '../button';
import { getScrollBarSize } from '../../utils/assist';
const prefixCls = 'ivu-modal';
export default {
components: { Icon, Button },
props: {
visible: {
type: Boolean,
default: false
},
closable: {
type: Boolean,
default: true
},
maskClosable: {
type: Boolean,
default: true
},
title: {
type: String
},
width: {
type: [Number, String],
default: 520
},
okText: {
type: String,
default: '确定'
},
cancelText: {
type: String,
default: '取消'
},
loading: {
type: Boolean,
default: false
},
style: {
type: Object
},
className: {
type: String
},
// for instance
footerHide: {
type: Boolean,
default: false
}
},
data () {
return {
prefixCls: prefixCls,
wrapShow: false,
showHead: true,
buttonLoading: false
}
},
computed: {
wrapClasses () {
return [
`${prefixCls}-wrap`,
{
[`${prefixCls}-hidden`]: !this.wrapShow,
[`${this.className}`]: !!this.className
}
]
},
maskClasses () {
return `${prefixCls}-mask`;
},
classes () {
return `${prefixCls}`;
},
styles () {
let style = {};
const styleWidth = {
width: `${this.width}px`
};
const customStyle = !!this.style ? this.style : {};
Object.assign(style, styleWidth, customStyle);
return style;
}
},
methods: {
close () {
this.visible = false;
this.$emit('on-cancel');
},
mask () {
if (this.maskClosable) {
this.close();
}
},
cancel () {
this.close();
},
ok () {
if (this.loading) {
this.buttonLoading = true;
} else {
this.visible = false;
}
this.$emit('on-ok');
},
EscClose (e) {
if (this.visible && this.closable) {
if (e.keyCode === 27) {
this.close()
}
}
},
checkScrollBar () {
let fullWindowWidth = window.innerWidth;
if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
const documentElementRect = document.documentElement.getBoundingClientRect();
fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
}
this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth;
if (this.bodyIsOverflowing) {
this.scrollBarWidth = getScrollBarSize();
}
},
setScrollBar () {
if (this.bodyIsOverflowing && this.scrollBarWidth !== undefined) {
document.body.style.paddingRight = `${this.scrollBarWidth}px`;
}
},
resetScrollBar () {
document.body.style.paddingRight = '';
},
addScrollEffect () {
this.checkScrollBar();
this.setScrollBar();
document.body.style.overflow = 'hidden';
},
removeScrollEffect() {
document.body.style.overflow = '';
this.resetScrollBar();
}
},
ready () {
if (this.visible) {
this.wrapShow = true;
}
let showHead = true;
if (this.$els.head.innerHTML == '<p></p>' && !this.title) {
showHead = false;
}
this.showHead = showHead;
// ESC close
document.addEventListener('keydown', this.EscClose);
},
beforeDestroy () {
document.removeEventListener('keydown', this.EscClose);
},
watch: {
visible (val) {
if (val === false) {
this.buttonLoading = false;
setTimeout(() => {
this.wrapShow = false;
}, 300);
this.removeScrollEffect();
} else {
this.wrapShow = true;
this.addScrollEffect();
}
}
}
}
</script>