2020-10-03 20:55:23 +08:00
|
|
|
<template>
|
2021-01-31 18:43:33 +08:00
|
|
|
<transition name="el-message-fade" @before-leave="onClose" @after-leave="$emit('destroy')">
|
2020-10-03 20:55:23 +08:00
|
|
|
<div
|
|
|
|
v-show="visible"
|
|
|
|
:id="id"
|
|
|
|
:class="[
|
|
|
|
'el-message',
|
|
|
|
type && !iconClass ? `el-message--${type}` : '',
|
|
|
|
center ? 'is-center' : '',
|
|
|
|
showClose ? 'is-closable' : '',
|
|
|
|
customClass,
|
|
|
|
]"
|
|
|
|
:style="customStyle"
|
|
|
|
role="alert"
|
|
|
|
@mouseenter="clearTimer"
|
|
|
|
@mouseleave="startTimer"
|
|
|
|
>
|
2021-07-28 10:07:51 +08:00
|
|
|
<i v-if="type || iconClass" :class="['el-message__icon', typeClass, iconClass]"></i>
|
2020-10-03 20:55:23 +08:00
|
|
|
<slot>
|
2021-01-31 18:43:33 +08:00
|
|
|
<p v-if="!dangerouslyUseHTMLString" class="el-message__content">{{ message }}</p>
|
2020-10-03 20:55:23 +08:00
|
|
|
<!-- Caution here, message could've been compromised, never use user's input as message -->
|
|
|
|
<!-- eslint-disable-next-line -->
|
|
|
|
<p v-else class="el-message__content" v-html="message"></p>
|
|
|
|
</slot>
|
2021-01-31 18:43:33 +08:00
|
|
|
<div v-if="showClose" class="el-message__closeBtn el-icon-close" @click.stop="close"></div>
|
2020-10-03 20:55:23 +08:00
|
|
|
</div>
|
|
|
|
</transition>
|
|
|
|
</template>
|
|
|
|
<script lang="ts">
|
2021-01-31 18:43:33 +08:00
|
|
|
import { defineComponent, computed, ref, PropType, onMounted, onBeforeUnmount } from 'vue'
|
2020-10-03 20:55:23 +08:00
|
|
|
// MessageVM is an alias of vue.VNode
|
|
|
|
import type { MessageVM } from './types'
|
2020-10-04 14:49:39 +08:00
|
|
|
import { EVENT_CODE } from '../../utils/aria'
|
2020-10-03 20:55:23 +08:00
|
|
|
import { on, off } from '../../utils/dom'
|
|
|
|
const TypeMap: Indexable<string> = {
|
|
|
|
success: 'success',
|
|
|
|
info: 'info',
|
|
|
|
warning: 'warning',
|
|
|
|
error: 'error',
|
|
|
|
}
|
|
|
|
export default defineComponent({
|
|
|
|
name: 'ElMessage',
|
|
|
|
props: {
|
|
|
|
customClass: { type: String, default: '' },
|
|
|
|
center: { type: Boolean, default: false },
|
|
|
|
dangerouslyUseHTMLString: { type: Boolean, default: false },
|
|
|
|
duration: { type: Number, default: 3000 },
|
|
|
|
iconClass: { type: String, default: '' },
|
|
|
|
id: { type: String, default: '' },
|
|
|
|
message: {
|
|
|
|
type: [String, Object] as PropType<string | MessageVM>,
|
|
|
|
default: '',
|
|
|
|
},
|
|
|
|
onClose: {
|
|
|
|
type: Function as PropType<() => void>,
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
showClose: { type: Boolean, default: false },
|
|
|
|
type: { type: String, default: 'info' },
|
|
|
|
offset: { type: Number, default: 20 },
|
|
|
|
zIndex: { type: Number, default: 0 },
|
|
|
|
},
|
2021-01-31 18:43:33 +08:00
|
|
|
emits: ['destroy'],
|
2020-10-03 20:55:23 +08:00
|
|
|
setup(props) {
|
|
|
|
const typeClass = computed(() => {
|
2021-07-27 09:08:46 +08:00
|
|
|
const type = !props.iconClass && props.type
|
2020-10-03 20:55:23 +08:00
|
|
|
return type && TypeMap[type]
|
2021-07-28 10:07:51 +08:00
|
|
|
? `el-icon-${TypeMap[type]}`
|
2020-10-03 20:55:23 +08:00
|
|
|
: ''
|
|
|
|
})
|
|
|
|
const customStyle = computed(() => {
|
|
|
|
return {
|
|
|
|
top: `${props.offset}px`,
|
|
|
|
zIndex: props.zIndex,
|
|
|
|
}
|
|
|
|
})
|
2021-01-31 18:43:33 +08:00
|
|
|
|
2020-10-03 20:55:23 +08:00
|
|
|
const visible = ref(false)
|
2021-01-31 18:43:33 +08:00
|
|
|
let timer = null
|
|
|
|
|
|
|
|
function startTimer() {
|
|
|
|
if (props.duration > 0) {
|
|
|
|
timer = setTimeout(() => {
|
|
|
|
if (visible.value) {
|
|
|
|
close()
|
2020-10-03 20:55:23 +08:00
|
|
|
}
|
2021-01-31 18:43:33 +08:00
|
|
|
}, props.duration)
|
2020-10-03 20:55:23 +08:00
|
|
|
}
|
2021-01-31 18:43:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function clearTimer() {
|
|
|
|
clearTimeout(timer)
|
|
|
|
timer = null
|
|
|
|
}
|
|
|
|
|
|
|
|
function close() {
|
|
|
|
visible.value = false
|
|
|
|
}
|
|
|
|
|
|
|
|
function keydown({ code }: KeyboardEvent) {
|
2020-10-04 14:49:39 +08:00
|
|
|
if (code === EVENT_CODE.esc) {
|
2020-10-03 20:55:23 +08:00
|
|
|
// press esc to close the message
|
2021-01-31 18:43:33 +08:00
|
|
|
if (visible.value) {
|
|
|
|
close()
|
2020-10-03 20:55:23 +08:00
|
|
|
}
|
|
|
|
} else {
|
2021-01-31 18:43:33 +08:00
|
|
|
startTimer() // resume timer
|
2020-10-03 20:55:23 +08:00
|
|
|
}
|
2021-01-31 18:43:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
startTimer()
|
|
|
|
visible.value = true
|
|
|
|
on(document, 'keydown', keydown)
|
|
|
|
})
|
|
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
|
off(document, 'keydown', keydown)
|
|
|
|
})
|
|
|
|
|
|
|
|
return {
|
|
|
|
typeClass,
|
|
|
|
customStyle,
|
|
|
|
visible,
|
|
|
|
|
|
|
|
close,
|
|
|
|
clearTimer,
|
|
|
|
startTimer,
|
|
|
|
}
|
2020-10-03 20:55:23 +08:00
|
|
|
},
|
|
|
|
})
|
|
|
|
</script>
|