parent
8c8a7b4aca
commit
5408210238
@ -0,0 +1,102 @@ |
||||
import Vue from 'vue' |
||||
import Main from './main.vue' |
||||
import {PopupManager} from 'element-ui/src/utils/popup' |
||||
import {isVNode} from 'element-ui/src/utils/vdom' |
||||
import {isEmpty} from "@/utils" |
||||
|
||||
let MessageConstructor = Vue.extend(Main) |
||||
|
||||
let instance |
||||
let instances = [] |
||||
let seed = 1 |
||||
|
||||
//键:options.type+'|'+options.message,值:message实例
|
||||
let groups = {} |
||||
|
||||
const Message = function (options) { |
||||
options = options || {} |
||||
if (typeof options === 'string') { |
||||
options = {message: options} |
||||
} |
||||
if (isEmpty(options.type)) { |
||||
options.type = 'info' |
||||
} |
||||
const group = options.type + '|' + options.message |
||||
const originalMessage = groups[group] |
||||
//若不是新的message
|
||||
if (originalMessage) { |
||||
//旧实例的badge+1,并重新计时(如果有的话)
|
||||
originalMessage.badge++ |
||||
originalMessage.clearTimer() |
||||
originalMessage.startTimer() |
||||
return originalMessage |
||||
} |
||||
|
||||
let userOnClose = options.onClose |
||||
let id = 'message_' + seed++ |
||||
|
||||
options.onClose = function () { |
||||
Message.close(id, userOnClose) |
||||
} |
||||
instance = new MessageConstructor({data: options}) |
||||
instance.id = id |
||||
instance.group = group |
||||
if (isVNode(instance.message)) { |
||||
instance.$slots.default = [instance.message] |
||||
instance.message = null |
||||
} |
||||
instance.$mount() |
||||
document.body.appendChild(instance.$el) |
||||
let verticalOffset = options.offset || 20 |
||||
instances.forEach(item => { |
||||
verticalOffset += item.$el.offsetHeight + 16 |
||||
}) |
||||
instance.verticalOffset = verticalOffset |
||||
instance.visible = true |
||||
instance.$el.style.zIndex = PopupManager.nextZIndex() |
||||
instances.push(instance) |
||||
groups[group] = instance |
||||
return instance |
||||
}; |
||||
|
||||
['success', 'warning', 'info', 'error'].forEach(type => { |
||||
Message[type] = options => { |
||||
if (typeof options === 'string') { |
||||
options = {message: options} |
||||
} |
||||
options.type = type |
||||
return Message(options) |
||||
} |
||||
}) |
||||
|
||||
Message.close = function (id, userOnClose) { |
||||
let len = instances.length |
||||
let index = -1 |
||||
let removedHeight |
||||
for (let i = 0; i < len; i++) { |
||||
if (id === instances[i].id) { |
||||
removedHeight = instances[i].$el.offsetHeight |
||||
index = i |
||||
if (typeof userOnClose === 'function') { |
||||
userOnClose(instances[i]) |
||||
} |
||||
delete groups[instances[i].group] |
||||
instances.splice(i, 1) |
||||
break |
||||
} |
||||
} |
||||
if (len <= 1 || index === -1 || index > instances.length - 1) return |
||||
for (let i = index; i < len - 1; i++) { |
||||
let dom = instances[i].$el |
||||
dom.style.top = |
||||
parseInt(dom.style.top, 10) - removedHeight - 16 + 'px' |
||||
} |
||||
} |
||||
|
||||
Message.closeAll = function () { |
||||
for (let i = instances.length - 1; i >= 0; i--) { |
||||
instances[i].close() |
||||
} |
||||
} |
||||
|
||||
export default Message |
||||
@ -0,0 +1,94 @@ |
||||
<template> |
||||
<transition name="el-message-fade" @after-leave="handleAfterLeave"> |
||||
<div v-show="visible" |
||||
:class="messageClass" |
||||
:style="positionStyle" |
||||
role="alert" |
||||
@mouseenter="clearTimer" |
||||
@mouseleave="startTimer" |
||||
> |
||||
<div v-if="badge>1" :key="badge" class="el-message__badge">{{badge}}</div> |
||||
<i v-if="iconClass" :class="iconClass"/> |
||||
<i v-else :class="typeClass"/> |
||||
<slot> |
||||
<p v-if="!dangerouslyUseHTMLString" class="el-message__content">{{ message }}</p> |
||||
<p v-else v-html="message" class="el-message__content"/> |
||||
</slot> |
||||
<i v-if="showClose" class="el-message__closeBtn el-icon-close" @click="close"/> |
||||
</div> |
||||
</transition> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
visible: false, |
||||
badge: 1, |
||||
message: '', |
||||
duration: 3000, |
||||
type: '', |
||||
iconClass: '', |
||||
customClass: '', |
||||
onClose: null, |
||||
showClose: false, |
||||
closed: false, |
||||
verticalOffset: 20, |
||||
timer: null, |
||||
dangerouslyUseHTMLString: false, |
||||
center: false |
||||
} |
||||
}, |
||||
computed: { |
||||
messageClass() { |
||||
return [ |
||||
'el-message', |
||||
this.type && !this.iconClass ? `el-message--${this.type}` : '', |
||||
this.center ? 'is-center' : '', |
||||
this.showClose ? 'is-closable' : '', |
||||
this.customClass |
||||
] |
||||
}, |
||||
typeClass() { |
||||
return this.type && !this.iconClass |
||||
? `el-message__icon el-icon-${this.type}` |
||||
: '' |
||||
}, |
||||
positionStyle() { |
||||
return { |
||||
'top': `${this.verticalOffset}px` |
||||
} |
||||
} |
||||
}, |
||||
watch: { |
||||
closed(newVal) { |
||||
if (newVal) { |
||||
this.visible = false |
||||
} |
||||
} |
||||
}, |
||||
methods: { |
||||
handleAfterLeave() { |
||||
this.$destroy(true) |
||||
this.$el.parentNode.removeChild(this.$el) |
||||
}, |
||||
close() { |
||||
this.closed = true |
||||
typeof this.onClose === 'function' && this.onClose(this) |
||||
}, |
||||
clearTimer() { |
||||
clearTimeout(this.timer) |
||||
}, |
||||
startTimer() { |
||||
if (this.duration > 0) { |
||||
this.timer = setTimeout(() => { |
||||
!this.closed && this.close() |
||||
}, this.duration) |
||||
} |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.startTimer() |
||||
} |
||||
} |
||||
</script> |
||||
Loading…
Reference in new issue