确认框是elementui最常用的组件之一,如何定制它呢?
下面这个例子是客户提出要用左右箭头键来控制按钮的焦点,使用键盘操控达到的提高办公效率的目的。
要实现这个目标有2种方法
1.修改elementui的源代码
2.对elementui的代码进行包装,添加键盘控制的功能
第一种方法需要读懂源代码花时间,而且不支持源代码升级,所以采取第二种办法。
如果你完整引入了 Element,它会为 Vue.prototype 添加如下全局方法:$msgbox, $alert, $confirm 和 $prompt。
通常这样使用:this.$confirm(message, title, options)
所以只要替换全局方法$confirm就达到包装的目的
包装$confirm组件
import Vue from 'vue'
var cancelButtonClass
var confirmButtonClass
var beforeCloseOrigin
function select(index) {
var buttons = document.querySelectorAll('.el-message-box__wrapper .el-message-box__btns button')
if (buttons.length !== 2) return
if (cancelButtonClass == null) {
cancelButtonClass = buttons[0].getAttribute('class')
confirmButtonClass = buttons[1].getAttribute('class')
}
buttons[0].setAttribute('class', index === 0 ? confirmButtonClass : cancelButtonClass)
buttons[1].setAttribute('class', index === 1 ? confirmButtonClass : cancelButtonClass)
buttons[index].focus()
}
function keyDownHandler(e) {
if (e.shiftKey && e.code === 'Tab' || e.code === 'ArrowLeft') {
select(0)
e.preventDefault()
} else if (!e.shiftKey && e.code === 'Tab' || e.code === 'ArrowRight') {
select(1)
e.preventDefault()
}
}
function beforeClose(action, instance, done) {
document.removeEventListener('keydown', keyDownHandler, false)
select(1)
if (beforeCloseOrigin) {
beforeCloseOrigin(action, instance, done)
} else {
done()
}
}
function confirm(message, title, options) {
cancelButtonClass = null
confirmButtonClass = null
var newTitle
var newOptions
if (typeof title !== 'string') {
newTitle = ''
newOptions = { ...title }
} else {
newTitle = title
newOptions = { ...options }
}
beforeCloseOrigin = newOptions.beforeClose
newOptions.beforeClose = beforeClose
document.addEventListener('keydown', keyDownHandler, false)
return Vue.prototype.$confirmOrigin.call(this, message, newTitle, newOptions)
}
export default function replaceConfirm() {
Vue.prototype.$confirmOrigin = Vue.prototype.$confirm
Vue.prototype.$confirm = confirm
}
新组件的核心思想是通过document.querySelectorAll来找到dom,然后操作dom来达到定制的目的。确认框是动态生成的,有模式的,所以用document.querySelectorAll能找到唯一的dom。监听键盘事件就可以达到键盘操控的目的,关闭的时候需要注销监听。
main.js
import Vue from 'vue'
import Element from 'element-ui'
...
// 引入confirm新组件
import replaceConfirm from '@/components/confirm'
...
// 替换confirm组件
replaceConfirm()
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})
在main.js中导入新组件,本来可以直接import '@/components/confirm',但是this.$confirm是异步完成的,直接调用发现this.$confirm还没有初始化,所以改成2步替换,目的就是等待this.$confirm完成初始化。