组件部分
<style scoped>
.alert-wrapper {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.6);
z-index: 2018;
}
.alert {
width: 400px;
padding: 0;
background-color: #fff;
border-radius: 4px;
overflow: hidden;
position: relative;
}
.close-icon {
position: absolute;
top: 5px;
right: 5px;
width: 32px;
height: 32px;
/* background: url('../../../assets/images/message_icon.png') 0px -20px no-repeat; */
background: url('../../assets/image/message_icon.png') 0px -20px no-repeat;
z-index: 10;
cursor: pointer;
}
.close-icon:hover {
background: url('../../assets/image/message_icon.png') 0px 6px
no-repeat;
}
.alert-title {
padding: 30px 32px 6px 60px;
box-sizing: border-box;
margin: 0;
font-size: 14px;
font-weight: bold;
color: #5e5e5e;
position: relative;
line-height: 20px;
text-indent: 38px;
}
.alert-title > .iconfont {
display: inline-block;
width: 34px;
height: 34px;
background: url('../../assets/image/message_icon.png') 0px -170px;
color: #ff8661;
position: absolute;
top: 22px;
left: 15px;
background-repeat: no-repeat;
}
.alert-title > .success {
background: url('../../assets/image/message_icon.png') 0px -170px;
}
.alert-title > .error {
background: url('../../assets/image/message_icon.png') 0px -90px;
}
.alert-title > .warn {
background: url('../../assets/image/message_icon.png') 0px -128px;
}
.alert-title.scrollable {
padding-bottom: 12px;
}
.alert-title.only-show-title {
padding-bottom: 36px;
}
.alert-body {
padding: 0px 24px 20px 60px;
width: 100%;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
color: #919191;
overflow-y: hidden;
white-space: pre-line;
}
.alert-body.only-show-content {
padding: 0;
}
.alert-body.body-scrollable {
overflow-y: auto;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.alert-actions {
padding: 10px 15px;
text-align: right;
}
.alert-actions .action-btn {
line-height: 36px;
padding: 0px 15px;
font-size: 12px;
border-radius: 3px;
outline: none;
border: 0;
box-sizing: border-box;
border: 1px solid #ccc;
background-color: #fff;
}
.alert-actions .confirm-btn {
margin-left: 15px;
/* border-color: #20a0ff; */
/* background-color: #20a0ff; */
border-color: #5aaa3c;
background-color: #5aaa3c;
color: #fff;
}
.alert-animate-enter-active,
.alert-animate-leave-active {
transition: opacity 0.45s;
}
.alert {
backface-visibility: hidden;
transition: transform 0.45s;
}
.alert-animate-enter,
.alert-animate-leave-active {
opacity: 0;
}
.alert-animate-enter .alert {
transform: translate3d(0, -64px, 0);
}
.alert-animate-leave-active .alert {
transform: translate3d(0, 64px, 0);
}
.clearfix:before,
.clearfix:after {
content: '';
clear: both;
line-height: 0;
height: 0;
visibility: hidden;
display: block;
}
</style>
<template>
<span>
<transition name="alert-animate">
<div class="alert-wrapper" v-if="open">
<div class="alert" ref="dialog">
<i @click="close($event)" class='close-icon'></i>
<h3 class="alert-title clearfix" v-if="showTitle" ref="title" :class="{'scrollable':scrollable,'only-show-title':!message&&!showFooter}">
<i class="iconfont" :class="icon[type]"></i>
<span>{{title}}</span>
<slot name="title">
</slot>
</h3>
<div class="alert-body" :class="{'only-show-content':!showTitle,'body-scrollable':scrollable}" v-if="message" ref="elBody" v-html="message">
</div>
<div class="alert-actions" v-if="showFooter" ref="footer" :class="{'scrollable':scrollable}">
<slot name="actions">
<button v-show="showCancelButton" class="action-btn cancel-btn" @click="handleFn('cancel',$event)">{{cancelButtonText}}</button>
<button v-show="showConfirmButton" class="action-btn confirm-btn" @click="handleFn('confirm',$event)">{{confirmButtonText}}</button>
</slot>
</div>
</div>
</div>
</transition>
</span>
</template>
<script>
/* 调用举例:
参数说明:
1.title: 弹窗标题
2.message: 弹窗内容 没有值可以不传 允许传html字符串
3.option : 配置项-> type: '', //icon 样式 success,dismiss 成功icon confirm warning 提示icon error 错误icon
scrollable: false, 是否启用滚动条
showConfirmButton: true, 是否显示确认按钮
showCancelButton: false, 是否显示取消按钮
confirmButtonText: '确定', 确认按钮文字
cancelButtonText: '取消', 取消按钮文字
closeDelay:1000, dismiss 延时关闭时间 (毫秒)
全局调用:
this.$confirm(title, message,option).then(() => {
console.log(确定按钮回调)
})
this.$dismiss('操作成功!',{
confirmButtonText: '知道了',
}).then(() => {
执行弹窗关闭后的代码
})
this.$warn('出错了', `<ul>
<li>${sdf}</li>
<li style="color:red;">2.年第三方啦</li>
<li>3.asf啊</li>
<li>4.阿萨德发</li>
</ul>`, {
confirmButtonText: '知道了',
type:'error'
}).then(() => {
console.log('error')
})
this.$success('操作成功!', {
confirmButtonText: '请确认',
showConfirmButton:true,
}).then(() => {
this.$dismiss('操作成功!')
})
*/
export default {
name: 'Alert',
data: function () {
return {
showConfirmButton: true,
showCancelButton: false,
confirmButtonText: '确定',
cancelButtonText: '取消',
action: '',
callback: null,
uid: 1,
title: undefined,
message: '',
type: '',
closeDelay: 1000,
scrollable: false,
timerId: null,
open: false,
// typehood:'',
icon: {
success: ' success',
dismiss: 'success',
confirm: 'warn',
warn: 'warn',
error: 'error'
}
}
},
props: {
alertObj: {
type: Object
// required:true,
}
},
computed: {
showTitle() {
return (
this.title ||
(this.$slots && this.$slots.title && this.$slots.title.length > 0)
)
},
showFooter() {
return (
(this.$slots &&
this.$slots.actions &&
this.$slots.actions.length > 0) ||
this.showConfirmButton ||
this.showCancelButton
)
}
},
mounted() { },
updated() {
this.$nextTick(() => {
this.setMaxContentHeight()
})
},
methods: {
handleFn: function (action, e) {
this.action = action
this.doClose(e)
},
//点击遮罩层关闭弹窗
close: function (e) {
if (!this.open) return
this.open = false
},
//事件处理
doClose() {
if (!this.open) return
this.open = false
if (this.action && this.action == 'confirm') {
this.callback(this.action, this) //'cancel' 取消事件不需要回调
}
// if (this.action) this.callback(this.action) //'cancel' 取消事件需要回调
},
addClass(elem, cls) {
if (!this.hasClass(elem, cls)) {
elem.className = elem.className == '' ? cls : elem.className + ' ' + cls
}
},
hasClass(elem, cls) {
cls = cls || ''
if (cls.replace(/\s/g, '').length == 0) return false //当cls没有参数时,返回false
return new RegExp(' ' + cls + ' ').test(' ' + elem.className + ' ')
},
closeAlert(e) {
if (this.type == 'dismiss') return
if (!this.open) return
this.open = false
},
//设置弹窗内容最大高度
setMaxContentHeight() {
const dom = this.$refs.dialog
if (!dom) return
if (!this.scrollable) {
dom.style.maxHeight = ''
return
}
let maxContentHeight = window.innerHeight * 0.7 //最大高度为clientHeight的70%
const { footer, title, elBody } = this.$refs
if (footer) maxContentHeight -= footer.offsetHeight
if (title) maxContentHeight -= title.offsetHeight
if (elBody) {
let maxBodyHeight = maxContentHeight
if (footer) maxBodyHeight -= footer.offsetHeight
if (title) maxBodyHeight -= title.offsetHeight
elBody.style.maxHeight = maxBodyHeight + 'px'
}
dom.style.maxHeight = maxContentHeight + 'px'
}
},
watch: {
open(val) {
if (val) this.uid++
if (val && this.type == 'dismiss') {
setTimeout(() => {
this.action = 'confirm'
this.doClose()
}, this.closeDelay)
}
}
}
}
</script>
js 封装
import Vue from 'vue'
import msgboxVue from '../components/component/messageBox.vue'
//默认参数
const defaults = {
title: undefined,
message: '',
type: '',
scrollable: false,
showConfirmButton: true,
showCancelButton: false,
confirmButtonText: '确定',
cancelButtonText: '取消',
closeDelay: 1500
}
const MessageBoxConstructor = Vue.extend(msgboxVue)
let currentMsg, MessageBoxVm //当前MessageBox对象 , messageBoxVm 实例
let msgQueue = [] //列队数组
//目标对象合并其他对象的属性
const merge = function (target) {
for (let i = 1, j = arguments.length; i < j; i++) {
let source = arguments[i] || {}
for (let prop in source) {
if (source.hasOwnProperty(prop)) {
let value = source[prop]
if (value !== undefined) {
target[prop] = value
}
}
}
}
return target
}
//回调函数(promise)
const defaultCallback = action => {
if (currentMsg) {
if (currentMsg.resolve) {
if (action === 'confirm') {
currentMsg.resolve(action)
} else if (action === 'cancel' && currentMsg.reject) {
currentMsg.reject(action)
}
}
}
}
//初始化
const initMessageBox = () => {
MessageBoxVm = new MessageBoxConstructor({
el: document.createElement('div')
})
MessageBoxVm.callback = defaultCallback
}
//执行下一个messageBox
const showNextMsg = () => {
if (!MessageBoxVm) {
initMessageBox()
}
MessageBoxVm.action = ''
if (!MessageBoxVm.open) {
if (msgQueue.length > 0) {
currentMsg = msgQueue.shift() //取出列队中的第一个对象执行
let options = currentMsg.options
for (let prop in options) {
if (options.hasOwnProperty(prop)) {
MessageBoxVm[prop] = options[prop]
}
}
if (options.callback === undefined) {
//当没有回调时 把Promise 当作回调
MessageBoxVm.callback = defaultCallback
}
let oldCb = MessageBoxVm.callback
MessageBoxVm.callback = (action, MessageBoxVm) => {
oldCb(action, MessageBoxVm)
showNextMsg()
}
document.body.appendChild(MessageBoxVm.$el)
Vue.nextTick(() => {
MessageBoxVm.open = true
})
}
}
}
const MessageBox = function (options, callback) {
if (typeof options === 'string') {
options = {
message: options
}
if (arguments[1]) {
options.title = arguments[1]
}
if (arguments[2]) {
options.type = arguments[2]
}
} else if (options.callback && !callback) {
callback = options.callback
}
if (typeof Promise !== 'undefined') {
return new Promise((resolve, reject) => {
msgQueue.push({
options: merge({}, defaults, MessageBox.defaults, options),
callback: callback,
resolve: resolve,
reject: reject
})
showNextMsg()
})
} else {
msgQueue.push({
options: merge({}, defaults, MessageBox.defaults, options),
callback: callback
})
showNextMsg()
}
}
//设置初始值
MessageBox.setDefaults = defaults => {
MessageBox.defaults = defaults
}
//确认对话框
MessageBox.confirm = (title, message, options) => {
if (typeof message === 'object') {
options = message
message = ''
} else if (message === undefined) {
message = ''
}
return MessageBox(
merge({
title: title,
message: message,
type: 'confirm',
$type: 'confirm',
showCancelButton: true
},
options
)
)
}
//成功对话框
MessageBox.success = (title, message, options) => {
if (typeof message === 'object') {
options = message
message = ''
} else if (message === undefined) {
message = ''
}
return MessageBox(
merge({
title: title,
type: 'success',
message: message,
$type: 'success'
},
options
)
)
}
//提示对话框
MessageBox.warn = (title, message, options) => {
if (typeof message === 'object') {
options = message
message = ''
} else if (message === undefined) {
message = ''
}
return MessageBox(
merge({
title: title,
type: 'warn',
confirmButtonText: '知道了',
message: message,
$type: 'warn'
},
options
)
)
}
//错误对话框
MessageBox.error = (title, message, options) => {
if (typeof message === 'object') {
options = message
message = ''
} else if (message === undefined) {
message = ''
}
return MessageBox(
merge({
title: title,
type: 'error',
confirmButtonText: '知道了',
message: message,
$type: 'error'
},
options
)
)
}
//自动关闭弹窗
MessageBox.dismiss = (title, message, options) => {
if (typeof message === 'object') {
options = message
message = ''
} else if (message === undefined) {
message = ''
}
return MessageBox(
merge({
title: title,
type: 'dismiss',
showConfirmButton: false,
message: message,
$type: 'dismiss'
},
options
)
)
}
MessageBox.close = () => {
if (MessageBoxVm) {
MessageBoxVm.open = false
}
msgQueue = []
currentMsg = null
}
export default MessageBox
export {
MessageBox
}
在main 中引入
import { MessageBox} from './plugins/messagebox.js'
//弹框
Vue.prototype.$confirm = MessageBox.confirm
Vue.prototype.$success = MessageBox.success
Vue.prototype.$warn = MessageBox.warn
Vue.prototype.$dismiss = MessageBox.dismiss
Vue.prototype.$error = MessageBox.error