Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<script>
/**
* Bootstrap Style Modal Component for Vue
* Depend on Bootstrap.css
*/
export default {
props: {
show: {
type: Boolean,
twoWay: true,
default: false
},
title: {
type: String,
default: 'Modal'
},
small: {
type: Boolean,
default: false
},
large: {
type: Boolean,
default: false
},
full: {
type: Boolean,
default: false
},
// 为true时无法通过点击遮罩层关闭modal
force: {
type: Boolean,
default: false
},
// 自定义组件transition
transition: {
type: String,
default: 'modal'
},
// 确认按钮text
okText: {
type: String,
default: 'OK'
},
// 取消按钮text
cancelText: {
type: String,
default: 'Cancel'
},
// 确认按钮className
okClass: {
type: String,
default: 'btn blue'
},
// 取消按钮className
cancelClass: {
type: String,
default: 'btn red btn-outline'
},
// 点击确定时关闭Modal
// 默认为false,由父组件控制prop.show来关闭
closeWhenOK: {
type: Boolean,
default: false
}
},
data: function() {
return {
duration: null
};
},
computed: {
modalClass: function() {
return {
'modal-lg': this.large,
'modal-sm': this.small,
'modal-full': this.full
}
}
},
created: function() {
if (this.show) {
document.body.className += ' modal-open';
}
},
beforeDestroy: function() {
document.body.className = document.body.className.replace(/\s?modal-open/, '');
},
watch: {
show (value) {
// 在显示时去掉body滚动条,防止出现双滚动条
if (value) {
document.body.className += ' modal-open';
}
// 在modal动画结束后再加上body滚动条
else {
if (!this.duration) {
this.duration = window.getComputedStyle(this.$el)['transition-duration'].replace('s', '') * 1000;
}
window.setTimeout(() => {
document.body.className = document.body.className.replace(/\s?modal-open/, '');
}, this.duration || 0);
}
}
},
methods: {
ok: function () {
this.$emit('ok');
if (this.closeWhenOK) {
this.show = false;
}
},
cancel: function() {
this.$emit('cancel');
this.show = false;
},
// 点击遮罩层
clickMask: function() {
if (!this.force) {
this.cancel();
}
}
}
};
</script>
<template>
<div v-show="show" :transition="transition">
<div class="modal" @click.self="clickMask">
<div class="modal-dialog" :class="modalClass" v-el:dialog>
<div class="modal-content">
<!--Header-->
<div class="modal-header">
<slot name="header">
<a type="button" class="close" @click="cancel"><span aria-hidden="true">×</span></a>
<h4 class="modal-title">
<slot name="title">
{{title}}
</slot>
</h4>
</slot>
</div>
<!--Container-->
<div class="modal-body">
<slot></slot>
</div>
<!--Footer-->
<div class="modal-footer">
<slot name="footer">
<button type="button" :class="cancelClass" @click="cancel">{{cancelText}}</button>
<button type="button" :class="okClass" @click="ok">{{okText}}</button>
</slot>
</div>
</div>
</div>
</div>
<div class="modal-backdrop in"></div>
</div>
</template>
<style scoped>
.modal-backdrop.in {
filter: alpha(opacity=50);
opacity: .5;
}
.modal-backdrop.fade {
filter: alpha(opacity=0);
opacity: 0;
}
.fade.in {
opacity: 1;
}
.modal-backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1040;
background-color: #000;
}
.modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1050;
display: block;
overflow: hidden;
-webkit-overflow-scrolling: touch;
outline: 0;
}
.fade {
opacity: 0;
-webkit-transition: opacity .15s linear;
-o-transition: opacity .15s linear;
transition: opacity .15s linear;
}
.modal-content {
position: relative;
background-color: #fff;
-webkit-background-clip: padding-box;
background-clip: padding-box;
border: 1px solid #999;
border: 1px solid rgba(0,0,0,.2);
border-radius: 6px;
outline: 0;
-webkit-box-shadow: 0 3px 9px rgba(0,0,0,.5);
box-shadow: 0 3px 9px rgba(0,0,0,.5);
}
.modal-header {
padding: 15px;
border-bottom: 1px solid #e5e5e5;
}
.modal-body {
position: relative;
padding: 15px;
}
.modal-footer {
padding: 15px;
text-align: right;
border-top: 1px solid #e5e5e5;
}
.modal.fade .modal-dialog {
-webkit-transition: -webkit-transform .3s ease-out;
-o-transition: -o-transform .3s ease-out;
transition: transform .3s ease-out;
-webkit-transform: translate(0,-25%);
-ms-transform: translate(0,-25%);
-o-transform: translate(0,-25%);
transform: translate(0,-25%);
}
@media (min-width: 768px) {
.modal-content {
-webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
}
}
@media (min-width: 768px) {
.modal-dialog {
width: 600px;
margin: 30px auto;
}
.modal-sm {
width: 300px;
}
}
@media (min-width: 992px){
.modal-lg {
width: 900px;
}
}
.modal-header .close {
margin-top: -2px;
cursor: pointer;
font-size: 36px;
font-weight: 200;
}
button.close {
-webkit-appearance: none;
padding: 0;
cursor: pointer;
background: 0 0;
border: 0;
}
.close {
float: right;
font-size: 21px;
font-weight: 700;
line-height: 1;
color: #000;
text-shadow: 0 1px 0 #fff;
filter: alpha(opacity=20);
opacity: .2;
}
.modal-transition {
transition: all .6s ease;
}
.modal-leave {
/* 样式没什么用,但可以让根标签的transitionEnd生效,以去掉modal-leave */
border-radius: 1px !important;
}
.modal-transition .modal-dialog, .modal-transition .modal-backdrop {
transition: all .5s ease;
}
.modal-enter .modal-dialog, .modal-leave .modal-dialog {
opacity: 0;
transform: translateY(-30%);
}
.modal-enter .modal-backdrop, .modal-leave .modal-backdrop {
opacity: 0;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment