先直接看最终效果展示
直接打开element form界面,将本文最下面的js文件粘贴到console中并执行 刚打开时的界面展示
console内执行代码后:
需求 - element form批量赋值
我们系统(element ui写的),有一个行内编辑的table界面,数据量比较大,并且输入项均为必需。 QA同学提了一个小需求,就是能不能帮她们做一个小工具,可以批量赋值的,可以提高她们的输入效率
初次尝试
这还不简单?N年前就干过。上来就干,先拿input试试
const inputList = document.querySelectorAll('.el-input')
for (const i of inputList) {
const inpEle = i.querySelector('.el-input__inner')
inpEle.setAttribute('value', 1)
}
粘贴到console中试一把,结果是界面显示数据设置上去了,但是保存的时候数据获取不到 为啥呢? 因为之前jQuery是从实际的input取值,然后继续下一步;现在是基于vue的开发,数据会存在data中,只操作dom里面的内容,是搞不定的
JS模拟键盘事件实现input输入
不能通过js直接修改dom的值,那咋办? 答案:只能通过js模拟键盘、鼠标事件,通过webapi的方式来调用 普通输入通过InputEvent可以模拟实现
const inputEvt = new InputEvent('input', {
inputType: 'insertText',
data: 1,
dataTransfer: null,
isComposing: false,
})
const inputList = document.querySelectorAll('.el-input')
for (const i of inputList) {
if (i.parentElement.classList.contains('el-select') || i.classList.contains('el-date-editor')) {
continue
}
const inpEle = i.querySelector('.el-input__inner')
inpEle.value = 1
inpEle.dispatchEvent(inputEvt)
}
相同操作,实现input type='textarea' 输入
这个与input类似,只是由于dom结构的不同,需要写两份代码
const inputEvt = new InputEvent('input', {
inputType: 'insertText',
data: 1,
dataTransfer: null,
isComposing: false,
})
const textareaList = document.querySelectorAll('.el-textarea')
for (const i of textareaList) {
const inpEle = i.querySelector('.el-textarea__inner')
inpEle.value = 1
inpEle.dispatchEvent(inputEvt)
}
JS模拟鼠标、键盘事件实现select选择
处理完input,还有一个重要的是select 这个需要 MouseEvent + KeyboardEvent 研究了一下select的规律,发现通过三步可以实现 1.获取到select的dom 2.派发点击事件 - 使select的选择列可以出来 3.派发键盘向下按键事件 - 选择第一个option 4.派发回车事件 - 完成select选中
代码如下
const mouseEvt = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window,
})
const downEvt = new KeyboardEvent('keydown', {
bubbles: true, cancelable: true, keyCode: 40,
})
const enterEvt = new KeyboardEvent('keydown', {
bubbles: true, cancelable: true, keyCode: 13,
})
const selectInputList = document.querySelectorAll('.el-select>.el-input')
for (const inpEle of selectInputList) {
inpEle.dispatchEvent(mouseEvt)
inpEle.dispatchEvent(downEvt)
inpEle.dispatchEvent(enterEvt)
}
js模拟鼠标事件,实现Radio、CheckBox的选择
有上面的input、select的处理经验,处理Radio、CheckBox应当更简单了 思路:遍历获取到Radio/CheckBox的外层元素,然后获取到其第一个节点,派发点击事件即可
const mouseEvt = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window,
})
const radioList = document.querySelectorAll('.el-radio-group')
for (const item of radioList) {
item.firstElementChild.dispatchEvent(mouseEvt)
}
const checkboxList = document.querySelectorAll('.el-checkbox-group')
for (const item of checkboxList) {
item.firstElementChild.dispatchEvent(mouseEvt)
}
试一把!有问题,第一个可以选中,后面的就不行了 研究了半天,发现了问题,对于Radio、CheckBox来说,MouseEvent不能复用,需要每次使用一个新的 修复版代码
function getMouseEvent() {
return new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window,
})
}
const radioList = document.querySelectorAll('.el-radio-group')
for (const item of radioList) {
item.firstElementChild.dispatchEvent(getMouseEvent())
}
const checkboxList = document.querySelectorAll('.el-checkbox-group')
for (const item of checkboxList) {
if (!item.firstElementChild.classList.contains('is-checked')) {
item.firstElementChild.dispatchEvent(getMouseEvent())
}
}
嗯,这下好使了……
添加上辅助代码,收尾
在界面右下角添加一个按钮,切换界面的时候,点击该按钮也会进行界面操作
function setValue () {
...
}
(function () {
const btn = document.createElement('input')
btn.type = 'button'
btn.style.position = 'fixed'
btn.style.bottom = '100px'
btn.style.right = '100px'
btn.style.zIndex = '9999'
btn.classList.add('el-button')
btn.classList.add('el-button--primary')
btn.value = '批量赋值'
btn.onclick = function () {
setValue()
}
document.body.appendChild(btn)
})()
最终版本代码地址如下:可以直接贴到console中允许
最终版js地址
前端小工具 - js模拟键盘、鼠标事件给element form批量赋值
总结
目前只是简单的实现了element ui的form赋值,同理,ant design的form赋值,也是类似的操作思想
InputEvent、MouseEvent、KeyboardEvent ,在作为webapi,在平常开发中使用的不多,可以通过其mdn的链接查看学习:Web API 接口参考
后面其实可以做的更精细, 比如进一步做成Chrome的插件,实现各种批量赋值的功能
|