是否可以在JavaScript中以编程方式模拟按键事件?


当前回答

你可以在EventTarget(元素,窗口,文档等)上分派键盘事件,如下所示:

element.dispatchEvent(new KeyboardEvent('keydown', {'key': 'a'}));

但是,dispatchEvent可能不会更新输入字段值,也可能不会触发常规键盘按下的行为,这可能是因为Event的原因。itrusted property,我不知道是否有办法绕过

但是你也可以通过设置输入值来改变输入。

element.value += "a";

例子:

let element = document.querySelector('input'); 元素。Onkeydown = e =>警报(e.key); changeValButton。Onclick =() =>元素。Value += "a"; dispatchButton。Onclick = () => { 元素。dispatchEvent(new KeyboardEvent('keydown', {'key': 'a'})); } <输入/ > <button id="dispatchButton">按下分派事件</button> <button id="changeValButton">按下按钮更改值</button> . </button id="changeValButton">


您可以根据需要向事件添加更多属性,如本答案所示。看一下KeyboardEvent文档

element.dispatchEvent(new KeyboardEvent("keydown", {
    key: "e",
    keyCode: 69, // example values.
    code: "KeyE", // put everything you need in this object.
    which: 69,
    shiftKey: false, // you don't need to include values
    ctrlKey: false,  // if you aren't going to use them.
    metaKey: false   // these are here for example's sake.
}));

    

此外,由于keypress已弃用,您可以使用keydown + keyup,例如:

element.dispatchEvent(new KeyboardEvent('keydown', {'key':'Shift'} ));
element.dispatchEvent(new KeyboardEvent( 'keyup' , {'key':'Shift'} ));

对于使用ReactJS的页面,这是一个尝试模拟键盘行为的线程

其他回答

一个非jquery版本,工作在webkit和gecko:

var keyboardEvent = document.createEvent('KeyboardEvent'); var initMethod = typeof keyboardEvent.initKeyboardEvent !== 'undefined' ? 'initKeyboardEvent' : 'initKeyEvent'; keyboardEvent[initMethod]( 'keydown', // event type: keydown, keyup, keypress true, // bubbles true, // cancelable window, // view: should be window false, // ctrlKey false, // altKey false, // shiftKey false, // metaKey 40, // keyCode: unsigned long - the virtual key code, else 0 0, // charCode: unsigned long - the Unicode character associated with the depressed key, else 0 ); document.dispatchEvent(keyboardEvent);

在某些情况下,按键事件不能提供所需的功能。从mozilla文档中我们可以看到该特性已被弃用:

不再推荐使用此特性。虽然一些浏览器可能仍然支持它,但它可能已经从相关的网络标准中删除了,可能正在被删除的过程中,或者可能只是为了兼容性的目的而保留。避免使用它,并尽可能更新现有代码;请参阅本页底部的兼容性表,以指导您的决定。请注意,此功能可能在任何时候停止工作。

因此,由于按键事件是由两个随后触发的事件keydown和接下来的同一个按键的keyup组合而成的,只需一个接一个地生成事件:

element.dispatchEvent(new KeyboardEvent('keydown',{'key':'Shift'}));
element.dispatchEvent(new KeyboardEvent('keyup',{'key':'Shift'}));

你可以在EventTarget(元素,窗口,文档等)上分派键盘事件,如下所示:

element.dispatchEvent(new KeyboardEvent('keydown', {'key': 'a'}));

但是,dispatchEvent可能不会更新输入字段值,也可能不会触发常规键盘按下的行为,这可能是因为Event的原因。itrusted property,我不知道是否有办法绕过

但是你也可以通过设置输入值来改变输入。

element.value += "a";

例子:

let element = document.querySelector('input'); 元素。Onkeydown = e =>警报(e.key); changeValButton。Onclick =() =>元素。Value += "a"; dispatchButton。Onclick = () => { 元素。dispatchEvent(new KeyboardEvent('keydown', {'key': 'a'})); } <输入/ > <button id="dispatchButton">按下分派事件</button> <button id="changeValButton">按下按钮更改值</button> . </button id="changeValButton">


您可以根据需要向事件添加更多属性,如本答案所示。看一下KeyboardEvent文档

element.dispatchEvent(new KeyboardEvent("keydown", {
    key: "e",
    keyCode: 69, // example values.
    code: "KeyE", // put everything you need in this object.
    which: 69,
    shiftKey: false, // you don't need to include values
    ctrlKey: false,  // if you aren't going to use them.
    metaKey: false   // these are here for example's sake.
}));

    

此外,由于keypress已弃用,您可以使用keydown + keyup,例如:

element.dispatchEvent(new KeyboardEvent('keydown', {'key':'Shift'} ));
element.dispatchEvent(new KeyboardEvent( 'keyup' , {'key':'Shift'} ));

对于使用ReactJS的页面,这是一个尝试模拟键盘行为的线程

在alex2k8的基础上,这里有一个修订版,可以在jQuery支持的所有浏览器中工作(问题是缺少jQuery.event的参数。触发器,在使用内部函数时很容易忘记它)。

// jQuery plugin. Called on a jQuery object, not directly.
jQuery.fn.simulateKeyPress = function (character) {
  // Internally calls jQuery.event.trigger with arguments (Event, data, elem).
  // That last argument, 'elem', is very important!
  jQuery(this).trigger({ type: 'keypress', which: character.charCodeAt(0) });
};

jQuery(function ($) {
  // Bind event handler
  $('body').keypress(function (e) {
    alert(String.fromCharCode(e.which));
    console.log(e);
  });
  // Simulate the key press
  $('body').simulateKeyPress('x');
});

您甚至可以更进一步,让它不仅模拟事件,而且实际插入字符(如果它是一个输入元素),但是在尝试这样做时,有许多跨浏览器的问题。最好使用更精致的插件,如SendKeys。

对于那些感兴趣的人,您可以可靠地重新创建键盘输入事件。为了更改输入区域中的文本(移动游标,或通过输入字符移动页面),必须严格遵循DOM事件模型:http://www.w3.org/TR/DOM-Level-3-Events/#h4_events-inputevents

该模型应该做到:

焦点(使用目标设置在DOM上分派)

然后对于每个字符:

keydown(在DOM上分派) Beforeinput(如果它是一个文本区域或输入,在目标分派) 按键(在DOM上分派) 输入(如果是文本区域或输入,则在目标处分派) 改变(如果它是一个选择,在目标分派) keyup(在DOM上分派)

然后,可选的大多数:

模糊(随目标设置在DOM上分派)

这实际上是通过javascript改变页面中的文本(不修改值语句),并适当地设置任何javascript侦听器/处理程序。如果你把顺序弄乱了,javascript就不会按适当的顺序触发,输入框中的文本不会改变,选择不会改变,或者光标不会移动到文本区域的下一个空格。

不幸的是,代码是为雇主写的,所以我不能分享它,但这绝对是可能的,但你必须以正确的顺序为每个元素重新创建整个关键输入“堆栈”。


编辑:我不是这个答案的原始海报,但我已经测试过了,我不能让它更新输入字段。下面是一个代码片段,其中的代码供其他人尝试或查看

let element = document.querySelector('input'); element.onkeydown = e => console.log('keydown on element: ' + e.key); document.onkeydown = e => console.log('keydown on document: ' + e.key + " " + e.target); dispatchButton.onclick = () => dispatchKey(element, 'a') dispatchKey = (target, key) => { let dom = document; // focus (dispatched on the DOM with the target set) let ev = new Event('focus', {target: target}); // this part seems to not work? when logging the // target in the onkeypress function it shows `document` instead of `input` // I also tried these and got the same behavior // ev.target = target; // and // Object.defineProperty(ev, 'target', {writable: false, value: target}); dom.dispatchEvent(ev); // keydown (dispatched on the DOM) dom.dispatchEvent(new KeyboardEvent('keydown', {'key': key, target: target})); // beforeinput (dispatched at the target if it's a textarea or input) target.dispatchEvent(new Event('beforeinput')); // keypress (dispatched on the DOM) dom.dispatchEvent(new KeyboardEvent('keypress', {'key': key})); // input (dispatched at the target if it's a textarea or input) target.dispatchEvent(new Event('input')); // change (dispatched at the target if it's a select) // keyup (dispatched on the DOM) dom.dispatchEvent(new KeyboardEvent('keyup', {'key': key})); // Then, optionally for most: // blur (dispatched on the DOM with the target set) dom.dispatchEvent(new Event('blur', {target: target})); console.log('dispatched'); } <input/> <button id="dispatchButton">Press to dispatch events </button>