【问题标题】:How to stop keydown event being stuck?如何停止keydown事件被卡住?
【发布时间】:2019-05-25 14:11:42
【问题描述】:

我希望下面列出的程序的行为是这样的:

  1. 我点击输入。
  2. 我按回车键。
  3. 出现“再次按 Enter”行。
  4. 我通过单击页面上的某处退出输入。
  5. 我按 Enter。
  6. 然后出现“您已按 Enter 2 次”行。

这个程序的真实行为:

  1. 我点击输入。
  2. 我按回车键。
  3. 出现“再次按 Enter”和“您已按 Enter 2 次”行。

我有两个问题:

1) 这是什么原因?我只按了一次 Enter。 2) 如何让这个程序按照我期望的方式运行?

let input = document.createElement("input");
input.value = "Click on this field and press Enter";
input.addEventListener("keydown", function(){
    if(event.keyCode === 13){
        let div2 = document.createElement("div");
        div2.innerHTML = "Press Enter once again";
        document.addEventListener("keydown", function(){
            if(event.keyCode === 13){
                let div3 = document.createElement("div");
                div3.innerHTML = "You have pressed Enter 2 times";
                document.body.appendChild(div3);
            }
        });
        document.body.appendChild(div2);    
    }
});
document.body.appendChild(input);

【问题讨论】:

  • 您正在附加事件侦听器两次。使用.preventDefault()?
  • 这个事件监听器被添加到不同的元素中。 .preventDefault() 没有帮助。
  • 另外,您已将事件侦听器附加到 document 而不是字段。随着事件冒泡,document 事件监听器执行。
  • 这是故意的。第一个 Enter 应该在字段上按,第二个可以在任何地方按
  • 啊。好的。使用event.stopPropagation()

标签: javascript events keydown dom-events onkeydown


【解决方案1】:

让我们分解一下。发生的情况是您的 if 条件会立即检查是否按下了键,并且一直如此 e.keyCode 始终为 13

解决这个问题的最简单方法是使用以下代码:

let input = document.createElement("input");
let isPressed = false;
input.value = "Click on this field and press Enter";
document.addEventListener("keydown", function(e) {
  if (event.keyCode === 13 && isPressed) {
    let div3 = document.createElement("div");
    div3.innerHTML = "You have pressed Enter 2 times";
    document.body.appendChild(div3);
  }
});
input.addEventListener("keydown", function(e){
    event.stopPropagation()
    if(event.keyCode === 13){
        if ( isPressed ) {
          return;
        } else {
          let div2 = document.createElement("div");
          div2.innerHTML = "Press Enter once again";
          isPressed = true;
          document.body.appendChild(div2); 
        }   
    }
});
document.body.appendChild(input);

你可以试试here。您可以根据自己的喜好进行折射。 :)

牢记您的原始代码,here 是更新版本。


要理解这个位是如何工作的,很简单:当元素 a 中有一个事件并且该元素的包装是 b 时,该事件会通过一个称为事件冒泡的过程向上传播(因为气泡 起来)。

因此,document 上的第二个事件侦听器被执行。

要阻止这种情况发生,您可以在 event 对象上使用 .stopPropagation()

【讨论】:

  • 非常感谢您的解决方案!有用。但是我还是不明白这个过程。在我的初始代码中,仅在按下 Enter 键后才添加第二个事件。那为什么会被激活呢?我按了一次 Enter 键,而不是两次。
  • 按一次,创建一个事件;此事件被您的inputeventListener 捕获。但是,事件仍然没有死;假设您没有在函数上调用return。然后,此事件沿您的 DOM 树向上传播,并被document 的事件侦听器捕获并执行两次。
【解决方案2】:

这里发生了几件事。您两次附加了侦听器,第二次是在整个文档上,然后当事件冒泡时立即触发此事件。如果您跟踪是否按下了输入,您也不需要为消息使用两个不同的元素。出于安全原因,您还应该使用textContent 而不是innerHTML :)

这里是重写的代码

let enterHasBeenPressed = false;

let input = document.createElement("input");
input.value = "Click on this field and press Enter";
input.addEventListener("keydown", function(){
    if(event.keyCode === 13){
        onEnterPressed();
    }
});
document.body.appendChild(input);

let text = document.createElement("div");
document.body.appendChild(text);

function onEnterPressed() {
    if (!enterHasBeenPressed) {
        text.textContent = "Press Enter once again";
        enterHasBeenPressed = true;
        return;
    }

    text.textContent = "You have pressed Enter 2 times";
}

https://codepen.io/anon/pen/wbjojR

【讨论】:

    猜你喜欢
    • 2022-09-27
    • 1970-01-01
    • 2019-11-26
    • 1970-01-01
    • 2019-04-06
    • 2021-11-22
    • 1970-01-01
    • 2012-08-05
    • 1970-01-01
    相关资源
    最近更新 更多