需求
打算在页面中自动填写账号密码,直接给文本框input元素赋值的方式无法触发键盘事件,导致数据不能提交(特殊的场景)。
所以改用javascript的模拟按键事件,但是UIEvent.initUIEvent和KeyboardEvent.initKeyEvent()等方法在最新的Chrome浏览器中已废弃。
按最新标准改用KeyboardEvent构造函数。
一、已废弃方法
最新规范(www.w3.org/TR/DOM-Level-3-Events/)中已弃用KeyboardEvent.initKeyEvent()方法。因此,Chrome没不支持此类方法。
function fireKeyEvent(el, evtType, keyCode) {
var evtObj;
if (document.createEvent) {
if (window.KeyEvent) {//firefox 浏览器下模拟事件
evtObj = document.createEvent('KeyEvents');
evtObj.initKeyEvent(evtType, true, true, window, true, false, false, false, keyCode, 0);
} else {//chrome 浏览器下模拟事件
evtObj = document.createEvent('UIEvents');
evtObj.initUIEvent(evtType, true, true, window, 1);
delete evtObj.keyCode;
if (typeof evtObj.keyCode === "undefined") {//为了模拟keycode
Object.defineProperty(evtObj, "keyCode", { value: keyCode });
} else {
evtObj.key = String.fromCharCode(keyCode);
}
if (typeof evtObj.ctrlKey === 'undefined') {//为了模拟ctrl键
Object.defineProperty(evtObj, "ctrlKey", { value: true });
} else {
evtObj.ctrlKey = true;
}
}
el.dispatchEvent(evtObj);
} else if (document.createEventObject) {//IE 浏览器下模拟事件
evtObj = document.createEventObject();
evtObj.keyCode = keyCode
el.fireEvent('on' + evtType, evtObj);
}
}
二、推荐方法
<html>
<head>365codes.com</head>
<body>
<input id="input_username"></input>
</body>
<script type="text/javascript">
function fireKeyEvent(element, evtType, keyChar) {
element.focus();
var KeyboardEventInit = {key:keyChar, code:"", location:0, repeat:false, isComposing:false};
var evtObj = new KeyboardEvent(evtType, KeyboardEventInit);
element.dispatchEvent(evtObj);
}
var objInput = document.getElementById("input_username");
objInput.addEventListener('keydown', function (e) {
objInput.value += e.key;
}, false);
fireKeyEvent(objInput,"keydown","a");
</script>
</html>
总结
参考标准文档:键盘事件 KeyboardEvent() - Web API 接口参考 | MDN
特别提醒:代码触发按键事件不会导致该字母自动出现在文本框中,所以在监听keydown事件中增加了input元素赋值,为了UI显示而已。各家浏览器出于安全原因设定,来防止脚本模拟与浏览器本身交互的操作。