【问题标题】:How to create KeyboardEvent with specific keyCode如何使用特定的 keyCode 创建 KeyboardEvent
【发布时间】:2016-11-10 17:07:00
【问题描述】:

我正在尝试在单元测试 (angular2/TypeScript) 中模拟 keydown 事件。我并不总是有可用的 DebugElement,所以我试图在本机元素上发出事件。 我遇到的问题是如何在创建键盘事件时定义 keyCode。 keyCode 未定义为 KeyboardEventInit 定义的一部分,并且在 KeyboardEvent 本身上它仅作为只读属性公开。

仅仅添加一个 keyCode 属性(并将 obj 类型设置为 )也不起作用。

    let elm = <HTMLElement>content.nativeElement;
    let ev = new KeyboardEvent('keydown', {
        code: '123',
        //keyCode: 345,
        key: 'a',
    });
    elm.dispatchEvent(ev);

有什么建议吗?

编辑: 根据 mdn 链接,不推荐使用 keyCode 并且不应使用,而应使用“代码”。 https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

【问题讨论】:

  • 你能解释一下你到底想做什么吗?
  • 似乎在fiddle 中工作,带有一个实际元素,你确定elm 包含一个带有捕获调度事件的事件处理程序的元素吗?
  • 是的,我有一个处理键盘输入的组件。我正在听 keyDown 并基于 keyCode 做例如滚动。不总是使用 Angular 的 DebugElement.triggerEventHandler 的原因是,一旦您以编程方式修改 DOM,DebugElement 似乎与 nativeElements 不同步。出于这个原因,我想在本机元素上调度事件 - 在我的单元测试中。
  • jsfiddle.net/5p0abvzq/2 是的,它适用于密钥,但不适用于我想要弄清楚的 keyCode
  • 啊,有人将我指向 mdn 链接 developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode 并明确指出 keyCode 已被弃用,不应使用。相反,应该使用“代码”。我将更改我的实现以使用代码而不是 keyCode

标签: javascript angular


【解决方案1】:

我仍然认为这是 Typescript 的错误,因为初始化程序 LanguageEvent 有。无论如何,解决方法是使用 Object.define 来设置 keyCode。

let arrowRight = new KeyboardEvent('keydown');
Object.defineProperty(arrowRight, 'keyCode', {
    get : () => 39
});
console.log(arrowRight.keyCode, arrowRight.key, arrowRight.code);

不管 keyCode 已被弃用,这并不意味着初始化程序不应该支持它。最有力的论据是 Internet Explorer 9 和 11 依赖于此,并且它们不支持 代码 https://caniuse.com/#search=event.code 或者完全支持key https://caniuse.com/#search=event.key 所以我认为 LanguageEvent 应该在其初始化程序中允许 keyCode。

let arrowRight = new KeyboardEvent('keydown', { keyCode: 39 });

【讨论】:

    【解决方案2】:

    keyCode 已被弃用,Angular 本身使用key 运行——我建议你重写你的逻辑来使用它。请记住,它依赖于浏览器——在 IE 空格键中是 Space,而在其他浏览器中是 EscEscape 也不同。不要记住任何其他不同的地方。

    【讨论】:

    • 那仍然没有回答 OP 问题。角度是否支持这一点不是争论。我认为这是一个打字稿问题。我们有 IE 9 或 IE 11 的情况呢?他们只发送 keyCode 而不是代码。在这些情况下,就会出现问题。您可以在 caniuse.com/#search=Event.key 此处查看代码和密钥 BrowserSupport,这与 IE 9 和 11 完全支持的 keyCode 形成对比。
    【解决方案3】:

    如果您使用 Angular,您可以设置键盘事件,并键入您的 HTML 模板并绑定到您的方法。

    请参阅 Angular 文档:https://angular.io/guide/user-input#key-event-filtering-with-keyenter

    而且由于您不需要测试 Angular API,因为它不是您正在测试的系统,您应该通过将模拟数据传递到您绑定关键事件的方法来编写单元测试。


    如果您指的是 UI/集成测试,那么所有这些都不是特别有用,因为上述内容实际上只对单元测试有效。

    【讨论】:

      【解决方案4】:

      或者例如,如果您想在用户按 CTRL+ALT+D 时运行一个函数,您的代码将如下所示。

       window.addEventListener('keydown', (event: KeyboardEvent) => {
             // Fall back to event.which if event.keyCode is null
             const keycode = event.keyCode || event.which;
             if (keycode === 68 && event.ctrlKey && event.altKey) {
               // Do stuff here
             }
          });
      

      【讨论】:

        【解决方案5】:

        看看:

        <!DOCTYPE html>
        <html>
        <body>
          <script>
          function EventHandler(e) {
            e = e || window.event;
            var code = typeof e.which !== 'undefined' ? e.which : e.keyCode; 
            if(code == 112 || code == 113 
                || code == 114 || code == 115
                || code == 116 || code == 117
                || code == 118 || code == 119
                || code == 120 || code == 121
                || code == 122 || code == 123) {
              e.returnValue = false;
              var target2 = document.getElementById("iFrameId"); 
              var targetBody = target2.contentDocument.body; 
              var keyboardEvent = document.createEvent("KeyboardEvent");
        
              Object.defineProperty(keyboardEvent, 'keyCode', {
                get : function() {
                  return this.keyCodeVal;
                }
              });
        
              Object.defineProperty(keyboardEvent, 'which', {
                get : function() {
                  return this.keyCodeVal;
                }
              });
        
              var initMethod = typeof keyboardEvent.initKeyboardEvent !== 'undefined' ? "initKeyboardEvent" : "initKeyEvent";
        
              keyboardEvent[initMethod](
                 "keydown", // event type : keydown, keyup, keypress
                 true, // bubbles
                 true, // cancelable
                 window, // viewArg: should be window
                 false, // ctrlKeyArg
                 false, // altKeyArg
                 false, // shiftKeyArg
                 false, // metaKeyArg
                 code, // keyCodeArg : unsigned long the virtual key code, else 0
                 0 // charCodeArgs : unsigned long the Unicode character associated with the depressed key, else 0
              );
              keyboardEvent.keyCodeVal = code;
              targetBody.dispatchEvent(keyboardEvent);        
            }
          }
          </script>
        
          <form>
            <input type="text" name="first" onkeydown="EventHandler()" > <br>
            <iframe id="iFrameId" src="frame.html" > </iframe>
          </form>
        </body>
        </html>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-27
          • 2014-04-29
          • 1970-01-01
          相关资源
          最近更新 更多