【问题标题】:Why is my event handler always one keystroke behind, and how does $timeout fix this?为什么我的事件处理程序总是落后一个按键,$timeout 如何解决这个问题?
【发布时间】:2014-01-17 19:19:28
【问题描述】:

我完全不明白为什么我的按键事件处理程序总是落后一键。 http://plnkr.co/edit/w3FAXGd5zjrktO6DgOpD?p=preview

<body ng-controller="myController">
  <form>
    <input ng-keypress="handleKeypress($event)" />
  </form>
</body>

控制器:

myapp.controller('myController', function($scope, $timeout){

    $scope.handleKeypress = function(ev){

      console.log(ev.target.value); //always one keystroke behind

      //$timeout(function(){console.log(ev.target.value);}); //works!

    };
}); 

为什么需要 $timeout 以及它为什么/如何工作? (最好是新手友好的答案)

我知道对于 keypress 事件,字符尚未插入 DOM,但我很困惑,因为 angularjs.org 的 Hello World 示例在释放键之前响应。他们的示例没有使用自定义事件处理程序,但显然 Angular 在 keyup 事件之前更新模型,所以我想了解更多关于在自定义事件处理程序中执行此操作的信息。

idursun 的回答指出 event.which 可在按键上使用,我认为 Angular 可能正在使用 String.fromCharCode(),但我在 Angular 源代码中没有看到任何关于此效果的内容。

【问题讨论】:

    标签: angularjs angularjs-directive


    【解决方案1】:

    您应该使用ng-keyup。按键可能并不总是按预期工作。

    来自 jQuery 文档:

    注意:由于keypress事件并未包含在任何官方规范中,使用它时遇到的实际行为可能因浏览器、浏览器版本和平台而异。

    【讨论】:

    • +1 我没有注意到这一点。我需要 keypess 的响应能力,但不响应 keydown 响应的所有额外键。 The spec says: "作者应该使用 beforeinput 事件而不是 keypress 事件。"但我找不到 beforeinput 的兼容性表。
    • @Jeltef event.preventDefault() 在输入类型号时不能与 ng-keyup 一起使用
    【解决方案2】:

    因为您的示例中的事件目标是一个输入元素,并且该元素尚未处理击键,所以该元素的value 始终是一个击键滞后。这使事件处理程序有机会拒绝按键。

    您可以通过查看事件对象的which 字段来检查按下的键值。

    【讨论】:

      【解决方案3】:

      tl:dr - event.target.value + event.key 会给你最新的值。

      它落后一步的原因是它允许您通过在注册之前触发事件来拒绝按键。这不是错误,而是一项功能。

      但是如果你想获得最新的值,这里有一个解决方法:-

      html:-

      <input type="text" (keypress)="myFunction($event)">
      

      JS:-

      myFunction(event) {
      event.preventDefault()
      console.log('latest input field value => ', event.target.value + event.key)
      }
      

      更新:-

      添加 event.preventDefault() 以避免出现双字符。

      更新2:-

      事件按以下顺序调用:-

      1. 按键
      2. 按键
      3. 更新视图
      4. 按键
      5. 更新视图
      6. 键位

      因此,如果您可以将此事件更改为keyup,那么您将获得最新的值,并且不必对方法进行额外的更改。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-06-13
        • 2021-05-07
        • 2021-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多