自定义消息弹出框组件(二次封装element-ui之MessageBox)

1 解决由于MessageBox打开后按钮自动聚焦导致的按钮处于active状态问题

element-ui提供的MessageBox有一个细节问题,当MessageBox打开后确定按钮会有一个自动聚焦的效果,导致组件渲染完成后确认按钮处于active状态,需要点击旁处使确认按钮失去焦点才能恢复正常的样式,效果如下:
MessageBox打开后按钮自动聚焦导致的按钮处于active状态
为了解决此问题,可以在MessageBox打开前设置一个1ms的延时,使遮罩层获取焦点:

open() {
  setTimeout(() => {
    document.querySelector('.el-message-box__wrapper').focus()
  }, 1)
  this.$confirm('此操作将永久删除该文件, 是否继续?', {
    title: '提示',
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    dangerouslyUseHTMLString: true,
    closeOnClickModal: false
  }).then(() => {
  }).catch(() => {
  })
}

在MessageBox打开前设置一个1ms的延时
虽然采用延时器的方法解决此问题比较low,但是目前我还没有想到第二种方法,欢迎大家集思广益。

2 调换MessageBox取消按钮和确定按钮的位置

element-ui提供的MessageBox默认的按钮样式是取消在前,确定在后:
在这里插入图片描述
若需求是确定在前,取消在后,那么可以通过下面的方法调换取消按钮和确定按钮的位置(messageTips是为了避免样式污染而通过customClass属性给MessageBox自定义的类名):

.messageTips .el-message-box__btns {
  display: flex;
  flex-direction: row-reverse;
  gap: 10px;
}

在这里插入图片描述

3 自定义MessageBox标题前的icon图标

通过CSS定位将.el-message-box__content中的icon固定在.el-message-box__header的前面:

this.$confirm('<i class="iconfont icon-tips"></i>此操作将永久删除该文件, 是否继续?', {
  title: '提示',
  confirmButtonText: '确定',
  cancelButtonText: '取消',
  dangerouslyUseHTMLString: true,
  customClass: 'messageTips'
}).then(() => {
}).catch(() => {
})
.icon-tips {
  font-size: 25px !important;
  color: orange;
  position: absolute;
  top: -40px;
}

.messageTips .el-message-box__header span {
  margin-left: 30px;
}

在这里插入图片描述

4 实现MessageBox底部的checkbox功能

通过CSS定位将.el-message-box__content中的.Prompt固定在.el-message-box__btns的前面:

open() {
  this.$confirm('<div class="Prompt"><input type="checkbox" id="Prompt-left"/><label for="Prompt-left"></label><span class="Prompt-right">不再提示</span></div>此操作将永久删除该文件, 是否继续?', {
    title: '提示',
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    dangerouslyUseHTMLString: true,
    customClass: 'messageTips'
  }).then(() => {
  }).catch(() => {
  })
  this.$nextTick(() => {
    document.getElementById('Prompt-left').addEventListener('change', this.handleUserCheck)
  })
},
handleUserCheck() {
  console.log(document.getElementById('Prompt-left').checked)
}
.messageTips .el-message-box__content {
  min-height: 68px;
}

.messageTips .Prompt {
  font-size: 14px;
  position: absolute;
  bottom: -87px;
  display: flex;
  align-items: center;
}

.Prompt > input {
  display: none;
}

.Prompt > label {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 2px;
  border: 1px solid #e4e7ed;
  margin-right: 5px;
  position: relative;
  cursor: pointer;
}

.Prompt > label::before {
  display: inline-block;
  content: " ";
  width: 8px;
  border: 2px solid #fff;
  height: 4px;
  border-top: none;
  border-right: none;
  border-color: #409eff;
  transform: rotate(-45deg);
  top: 2px;
  left: 2px;
  position: absolute;
  opacity: 0;
}

.Prompt > input:checked+label {
  background-color: #fff;
  border-color: #409eff;
}

.Prompt > input:checked+label::before {
  opacity: 1;
  transform: all 0.5s;
}

在这里插入图片描述

5 点击MessageBox遮罩层的抖动效果

通过beforeClose属性在关闭MessageBox前设置判断逻辑,但是注意配合distinguishCancelAndClose:true和closeOnClickModal:false才能生效:

this.$confirm('此操作将永久删除该文件, 是否继续?', {
  title: '提示',
  confirmButtonText: '确定',
  cancelButtonText: '取消',
  dangerouslyUseHTMLString: true,
  distinguishCancelAndClose: true,
  customClass: 'messageTips',
  beforeClose: (action, instance, done) => {
    const clickEvent = (event) => {
      if (action === 'confirm' || action === 'cancel') {
        done()
      } else {
        if (event.target.classList[0] === 'el-message-box__wrapper') {
          const messageBox = document.querySelector('.messageTips')
          messageBox.style.transform = 'scale(1.01)'
          setTimeout(() => {
            messageBox.style.transform = 'scale(1)'
          }, 150)
        } else if (event.target.classList[0] === 'el-message-box__close') {
          done()
        }
      }
      document.body.removeEventListener('click', clickEvent)
    }
    document.body.addEventListener('click', clickEvent)
  }
}).then(() => {
}).catch(() => {
})

在这里插入图片描述

6 完整效果展示

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值