element-ui $message仅加载一次,添加抖动动画、重置展示时间(重新整理)

1、需求

需求产生原因:

  1. 多次调用$message导致页面message提示加载过多(满屏)

  1. 相同的message提示多次出现

需求修改后优点:

  1. $message只创建一次,不会出现满屏情况

  1. 相同的message重复使用

  1. 添加抖动,用户注意力聚焦

2、实现思路

要求:

  1. 单独封装,重新定义全局$message,所有调用的的$message都走封装好的方法

  1. 使用方法需要与element-ui使用方法一致,不影响旧的$message的使用

需求分析:

  1. 获取element-ui 的 $message(Message)实例,单独封装singleMessage方法

  1. 当前不存在message

  1. 第一次调用$message方法,不存在已经创建过的message,则调用Message创建一条message

  1. 当前存在message

  1. 需要创建的message与上一个已存在的message类型和内容不相同,关闭当前Message实例,再次调用Message创建新的不同的message

  1. 需要创建的message与上一个已存在的message类型和内容相同,不在调用Message创建message,而是重复使用当前message,并且添加抖动动画提示用户当前操作结果一致,并且清除已经开始计算关闭message的倒计时,重置当前message的展示时间

  1. 重写$message.Type('success', 'warning', 'info', 'error')方法

  1. 当前$message.Type(option)方法

  1. 传入的opstion为字符串,opstion赋值给options的message,当前type赋值给options的type;

  1. 当前传入的option为对象,option赋值给options,当前type赋值给options的type

  1. 使用方式

  1. main.js 文件

  1. 因为几乎都是全局在用,所以直接挂载在Vue.prototype 上

  1. 引入:import message from '@/utils/resetMessage.js'

  1. Vue.prototype.$message = message 一定要写在 Vue.use(ElementUI) 下边,否则无效,代码先后顺序问题

  1. 局部使用:

  1. 引入:import singleMessage from '@/utils/resetMessage.js'

  1. singleMessage.error('123123123')

  1. singleMessage.error({message: '123123', duration: 10000})

  1. singleMessage({message: '123123', type: 'error', duration: 10000})

需要使用到的实例方法:

关闭:close()

清除关闭倒计时:clearTimer()

重新计算关闭倒计时:startTimer()

实现代码

// 仅个人开发记录
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():

  1. 关键帧 (参数可以是数组或对象,数组内包裹的也必须是对象,对象中为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)',
            },
         ],
  1. 动画属性设置 {参数数字或者对象}

属性大致有以下 :

  • duration: 动画时长 (单位毫秒)

  • iterations :重复次数[默认:1,无限循环:‘Infinity’]

  • fill :结束时复位 [不复位:forwards, 复位(默认值):none]

  • delay : 动画延迟时长 (毫秒)

  • easing :动画 运动速率 [esse(默认):慢-快-慢 ,linear: 匀速, ease-in: 慢-匀速, ease-in-out 慢-匀速-慢]

使用:

疑问点

  1. 为什么cloneOptions要定义在函数外边

cloneOptions做什么用:对比本次需创建的message和上次创建后仍在页面上的message是否一致

因为cloneOptions 是用来和上一次创建的$message 的类型做比较的,而每次调用$message都会走拦截的resetMessage方法,当第一次创建$message之前,还没有message的信息,cloneOptions自然就为空对象{},但是当第二次创建message的时候,如果把cloneOptions放在函数内部,当再次调用$message创建的时候,cloneOptions始终都为是{},那么cloneOptions和本次的message的类型作对比的时候始终都不一致(isEqual(compareMessage, cloneOptions) 为 false),都会再次创建一个新的,但是类型一致的message

  1. 为什么末尾要从clone一遍compareMessage

创建message后,用于记录本次创建的message的信息,再次创建时需要此对象用作对比是否需要再次创建新的message或者是重复使用当前的message

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值