Created
August 14, 2016 14:27
-
-
Save reg2005/f44442fe4ba6ae07be404826e79aa02e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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