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