1、需求
需求产生原因:
多次调用$message导致页面message提示加载过多(满屏)
相同的message提示多次出现
需求修改后优点:
$message只创建一次,不会出现满屏情况
相同的message重复使用
添加抖动,用户注意力聚焦
2、实现思路
要求:
单独封装,重新定义全局$message,所有调用的的$message都走封装好的方法
使用方法需要与element-ui使用方法一致,不影响旧的$message的使用
需求分析:
获取element-ui 的 $message(Message)实例,单独封装singleMessage方法
当前不存在message
第一次调用$message方法,不存在已经创建过的message,则调用Message创建一条message
当前存在message
需要创建的message与上一个已存在的message类型和内容不相同,关闭当前Message实例,再次调用Message创建新的不同的message
需要创建的message与上一个已存在的message类型和内容相同,不在调用Message创建message,而是重复使用当前message,并且添加抖动动画提示用户当前操作结果一致,并且清除已经开始计算关闭message的倒计时,重置当前message的展示时间
重写$message.Type('success', 'warning', 'info', 'error')方法
当前$message.Type(option)方法
传入的opstion为字符串,opstion赋值给options的message,当前type赋值给options的type;
当前传入的option为对象,option赋值给options,当前type赋值给options的type
使用方式
main.js 文件
因为几乎都是全局在用,所以直接挂载在Vue.prototype 上
引入:import message from '@/utils/resetMessage.js'
Vue.prototype.$message = message 一定要写在 Vue.use(ElementUI) 下边,否则无效,代码先后顺序问题
局部使用:
引入:import singleMessage from '@/utils/resetMessage.js'
singleMessage.error('123123123')
singleMessage.error({message: '123123', duration: 10000})
singleMessage({message: '123123', type: 'error', duration: 10000})
![](https://i-blog.csdnimg.cn/blog_migrate/d0f2ce70ff04b8b6d610d8af5fcbad08.png)
需要使用到的实例方法:
关闭:close()
清除关闭倒计时:clearTimer()
重新计算关闭倒计时:startTimer()
![](https://i-blog.csdnimg.cn/blog_migrate/28f83b3cc037b495e20b68fb8d063315.png)
实现代码
// 仅个人开发记录
import { Message } from 'element-ui'
import { cloneDeep, isEqual } from 'lodash'
let messageInstance = null
let cloneOptions = {}
const resetMesage = option => {
const options = {
offset: 50,
...option,
}
const { type, message } = options
// 用来作比较
const compareMessage = { type, message }
const messageDom = document.getElementsByClassName('el-message')[0]
if (messageDom === undefined) {
messageInstance = Message(options)
console.log(messageInstance)
} else if (
messageDom !== undefined &&
!isEqual(compareMessage, cloneOptions)
) {
// 类型不一致关闭上一个实例,再次创建实例
messageInstance.close()
messageInstance = Message(options)
} else if (
messageDom !== undefined &&
isEqual(compareMessage, cloneOptions)
) {
// 类型一致抖动,重置展示时间
messageDom.classList.add('message-shaking')
messageInstance.clearTimer()
messageInstance.startTimer()
// 新增动画
const timer = setTimeout(() => {
messageDom.classList.remove('message-shaking')
clearTimeout(timer)
}, 150)
}
cloneOptions = cloneDeep(compareMessage)
}
// 重新设置message的类型方法
;['success', 'warning', 'info', 'error'].forEach(type => {
resetMesage[type] = function (option) {
let options = option || {}
if (typeof option === 'string') {
options = {
message: option,
}
}
options.type = type
return resetMesage(options)
}
})
const message = resetMesage
export default message
使用
import message from '@/utils/resetMessage.js'
Vue.use(ElementUI)
Vue.prototype.$message = message
也可以局部使用
import singleMessage from '@/utils/resetMessage.js'
//
singleMessage.error('message')
// 或者
singleMessage({
type: 'error',
message: '123123'
})
抖动动画css,在element-ui位移原基础上加的抖动
.message-shaking {
animation: shaking 0.15s 4 linear;
}
@keyframes shaking {
0% {
transform: translate(calc(-50% - 1px), -1px);
}
20% {
transform: translate(-50%, 0);
}
40% {
transform: translate(calc(-50% + 1px), 1px);
}
60% {
transform: translate(calc(-50%), 0);
}
80% {
transform: translate(calc(-50% + 1px), 1px);
}
100% {
transform: translate(calc(-50% - 1px), -1px);
}
}
源码地址
https://github.com/ElemeFE/element/blob/dev/packages/message/src/main.js
4、修改:
根据组长提供的思路--去掉删除类名的定时器,添加关键帧,找到了一个方法:Dom.animate()
Dom.animate():
关键帧 (参数可以是数组或对象,数组内包裹的也必须是对象,对象中为css属性和值)
{ transform: 'translate(calc(-50% - 1px), -1px)' }
// or
[
{ transform: 'translate(calc(-50% - 1px), -1px)' },
{
transform: 'translate(-50%, 0)',
},
{
transform: 'translate(calc(-50% + 1px), 1px)',
},
{
transform: 'translate(calc(-50%), 0)',
},
{
transform: 'translate(calc(-50% + 1px), 1px)',
},
{
transform: 'translate(calc(-50% - 1px), -1px)',
},
],
动画属性设置 {参数数字或者对象}
属性大致有以下 :
duration: 动画时长 (单位毫秒)
iterations :重复次数[默认:1,无限循环:‘Infinity’]
fill :结束时复位 [不复位:forwards, 复位(默认值):none]
delay : 动画延迟时长 (毫秒)
easing :动画 运动速率 [esse(默认):慢-快-慢 ,linear: 匀速, ease-in: 慢-匀速, ease-in-out 慢-匀速-慢]
使用:
![](https://i-blog.csdnimg.cn/blog_migrate/e6d9133a40224a2c92a5aa568c78aea6.png)
疑问点
为什么cloneOptions要定义在函数外边
cloneOptions做什么用:对比本次需创建的message和上次创建后仍在页面上的message是否一致
因为cloneOptions 是用来和上一次创建的$message 的类型做比较的,而每次调用$message都会走拦截的resetMessage方法,当第一次创建$message之前,还没有message的信息,cloneOptions自然就为空对象{},但是当第二次创建message的时候,如果把cloneOptions放在函数内部,当再次调用$message创建的时候,cloneOptions始终都为是{},那么cloneOptions和本次的message的类型作对比的时候始终都不一致(isEqual(compareMessage, cloneOptions) 为 false),都会再次创建一个新的,但是类型一致的message
为什么末尾要从clone一遍compareMessage
创建message后,用于记录本次创建的message的信息,再次创建时需要此对象用作对比是否需要再次创建新的message或者是重复使用当前的message
![](https://i-blog.csdnimg.cn/blog_migrate/49b10bc0ffda9c8ece8bbfb7d0b47e23.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d0562984356e299aeb8e837eb90cccea.png)