ElMessageBox.confirm增加确认按钮倒计时禁用功能
·
1、新建工具文件 utils/messageBox.js
// utils/messageBox.js
import {
ElMessageBox
} from 'element-plus'
export function confirmCountDown(title, message, waitSecond = 5, options = {}) {
const totalSec = Math.max(1, Number(waitSecond) || 5)
let timer = null
let count = totalSec
let observer = null
// 销毁清理
const destroy = () => {
timer && clearInterval(timer)
timer = null
observer && observer.disconnect()
observer = null
}
const boxOpts = {
cancelButtonText: '取消',
closeOnClickModal: false,
beforeClose: (_action, _ins, done) => {
destroy()
done()
},
...options
}
return new Promise((resolve, reject) => {
const boxPromise = ElMessageBox.confirm(message, title, boxOpts)
boxPromise
.then(() => {
destroy()
resolve(true)
})
.catch(() => {
destroy()
reject(false)
})
observer = new MutationObserver(() => {
const confirmBtn = document.querySelector('.el-message-box__btns .el-button--primary')
if (!confirmBtn) return
observer.disconnect()
setTimeout(() => {
// 封装统一设置禁用状态方法
const setDisabled = (status) => {
confirmBtn.disabled = status
if (status) {
confirmBtn.classList.add('is-disabled')
} else {
confirmBtn.classList.remove('is-disabled')
}
}
// 初始禁用
setDisabled(true)
confirmBtn.innerText = `确认(${count}s)`
timer = setInterval(() => {
count--
if (count > 0) {
setDisabled(true)
confirmBtn.innerText = `确认(${count}s)`
} else {
setDisabled(false)
confirmBtn.innerText = '确认'
destroy()
}
}, 1000)
}, 50)
})
observer.observe(document.body, {
childList: true,
subtree: true
})
})
}
2、页面中使用(Vue3 setup)
<template>
<el-button type="danger" @click="handleDelete">删除数据</el-button>
</template>
<script setup>
import { confirmCountDown } from '@/utils/messageBox'
import { ElMessage } from 'element-plus'
const handleDelete = async () => {
try {
// 第二个参数倒计时6秒,第三个可传原生配置
await confirmCountDown('危险操作', '删除后数据无法恢复,请谨慎操作', 6, {
type: 'error', // 弹窗图标类型
closeOnPressEscape: false // 禁止ESC关闭
})
// 点击确认且倒计时结束才能走到这里
ElMessage.success('删除成功')
} catch {
ElMessage.info('已取消删除')
}
}
</script>
3、全局挂载(可选,main.js)
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import { confirmCountDown } from '@/utils/messageBox'
const app = createApp(App)
app.use(ElementPlus)
// 全局挂载
app.config.globalProperties.$confirmCountDown = confirmCountDown
app.mount('#app')
全局调用写法:
const { proxy } = getCurrentInstance()
proxy.$confirmCountDown('提示', '确定提交?', 3)
关键优化细节说明
- 用 requestAnimationFrame 替代 setTimeout (0) 更精准等待 DOM 渲染,比宏任务时序更稳定,低帧率页面也不会获取不到按钮
- 全场景定时器销毁
beforeClose、then 确认、catch 取消三大分支全部执行 clearTimer,彻底杜绝内存泄漏、多定时器叠加 - 数值容错 传入 0、负数、字符串数字都会自动修正为最少 1 秒倒计时
- try-catch 包裹 DOM 操作 弹窗销毁瞬间还在执行更新逻辑不会抛红报错
- 配置透传 原生 ElMessageBox 所有参数(type、center、input、closeOnPressEscape 等)全部支持自定义传入
- Promise 标准格式 then 代表确认,catch 代表所有关闭行为,符合业务常规写法
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)