Vue - 实现消息通知组件及插件
效果图功能分解动画计算高度组件源码<template><div class="ys-message-wrapper animated fadeInDown"><div class="ys-message-toast"><img :src="curren
·
效果图
功能分解
- 动画
- 计算高度
组件源码
<template>
<div class="ys-message-wrapper animated fadeInDown">
<div class="ys-message-toast">
<img :src="currentType" alt="">
<p>{{text}}</p>
</div>
</div>
</template>
<script>
export default {
name: 'Message',
props: {
text: {
type: String,
default: '提示信息'
},
type: {
type: String,
default: 'info'
}
},
data () {
return {
src: [require('../../assets/icon/info.svg'), require('../../assets/icon/warn.svg'), require('../../assets/icon/error.svg'), require('../../assets/icon/success.svg')]
}
},
computed: {
currentType () {
let i
switch (this.type) {
case 'info':
i = 0
break
case 'warn':
i = 1
break
case 'error':
i = 2
break
case 'success':
i = 3
break
default:
i = 0
}
return this.src[i]
}
}
}
</script>
<style lang="less" scoped>
.ys-message-wrapper{
width: 80%;
min-height: 30px;
position: absolute;
left: 50%;
animation-duration: 0.5s;
display: flex;
justify-content: center;
align-items: center;
transition: all 0.5s;
.ys-message-toast{
max-width: 100%;
pointer-events: none;
padding: 8px 12px;
border-radius: 4px;
box-shadow: 0 1px 6px rgba(0,0,0,.2);
background: #fff;
display: flex;
justify-content: center;
align-items: center;
img{
width: 15px;
height: 15px;
object-fit: contain;
margin: 0 8px 0 0;
}
p{
max-width: 100%;
font-size: 14px;
word-break: keep-all;
word-wrap: break-word;
}
}
}
.fadeInDown{
animation-name: fadeInDown
}
@keyframes fadeInDown {
from {
opacity: 0;
transform: translate3d(-50%, -100%, 0);
}
to {
opacity: 1;
transform: translate3d(-50%, 0, 0);
}
}
</style>
重头戏在这呢
实现的基本原理主要是两个:
- 使用point-event点透,防止遮罩层挡住页面
- 使用一个全局数组(栈)记录当前在dom中的message组件
插件源码
import MessageVue from '../../components/Message/Message'
const MessageBox = {}
MessageBox.install = (Vue, options) => {
const MessageBoxInstance = Vue.extend(MessageVue)
let currentMsg
let msgBoxElList = []
const initInstance = () => {
if (document.querySelector('#message-container')) {
} else {
let template = '<div id="message-container" style="position: fixed;top: 15px;z-index:100;pointer-events:none;width: 100%;height: 100%;">' +
'<div id="message-wrapper" style="position: relative;width: 100%;height: 100%;"></div>' +
'</div>'
let T = Vue.extend({template: template})
let container = new T().$mount().$el
document.body.appendChild(container)
}
currentMsg = new MessageBoxInstance()
}
const mount = () => {
let msgBoxEl = currentMsg.$mount().$el
let list = document.querySelectorAll('.ys-message-wrapper')
if (list.length) {
msgBoxEl.style.top = parseInt(list[list.length - 1].style.top) + list[list.length - 1].clientHeight + 15 + 'px'
} else {
msgBoxEl.style.top = 15 + 'px'
}
document.querySelector('#message-wrapper').appendChild(msgBoxEl)
msgBoxElList.unshift(msgBoxEl)
}
Vue.prototype.$message = opt => {
initInstance()
if (typeof opt === 'string') {
currentMsg.text = opt
} else if (typeof opt === 'object') {
Object.assign(currentMsg, opt)
}
mount()
setTimeout(() => {
let el = msgBoxElList.pop()
el.style.top = 0
setTimeout(() => {
document.querySelector('#message-wrapper').removeChild(el)
}, 500) // transition时间是0.5s
// 当message都自动销毁以后,不需要销毁container了...缓存在这里
}, 1500)
}
}
export default MessageBox
更多推荐
已为社区贡献16条内容
所有评论(0)