删除 .keydown() 中的一个样本捕获延迟

Remove one-sample capture delay in .keydown()

出于特殊原因,我使用 JQuery 的 keydown() 事件来过滤隐藏输入字段中的击键。然后输入字段的值被复制到一个可见的 div。问题是由于某种原因,我按下的键在我下次按下一个键时被复制到 div,这意味着输入被延迟了一个周期。

我试过 keyup() 并且这个确实有效,但是我不喜欢在释放键时更新值的行为。如何在保持 keydown() 的同时进行即时更新?

var wordInput = '';

$('#input').keydown(function(event) {
    var keycode = event.which;
    switch(keycode) {
     // Enter key
     case 13:  
      console.log('Submit');
     // Space key
        case 32:  
         console.log('Space disabled');
         break;
     // Backspace
     case 8:
            // Subscract the last char
            wordInput = wordInput.substr(0, wordInput.length - 1);
      break;
     // Any other key
  default:  
   // If char limit not exceeded
   if (wordInput.length < 20) {
                wordInput += $('#input').val(); // Add the typed letter
            }             
    }
    // Update the word displayed
    $('#story-input').html(wordInput);
    // Clear the  input
    $('#input').val('');
});

查看示例:http://jsfiddle.net/mqbxqLp7/

对于这种情况,jQuery 的 keyup() 挂钩可能更合适。这样,它只会在释放键并且值在输入框中后触发。这应该使它更平滑,消除下一次按键触发前一次推送到该值,而不是在当前按键结束时触发。 (包含代码段中的演示。)

var wordInput = '';

$('#input').keyup(function(event) {
    var keycode = event.which;
    switch(keycode) {
     // Enter key
     case 13:  
      console.log('Submit');
     // Space key
        case 32:  
         console.log('Space disabled');
         break;
     // Backspace
     case 8:
            // Subscract the last char
            wordInput = wordInput.substr(0, wordInput.length - 1);
      break;
     // Any other key
  default:  
   // If char limit not exceeded
   if (wordInput.length < 20) {
                wordInput += $('#input').val(); // Add the typed letter
            }             
    }
    // Update the word displayed
    $('#story-input').html(wordInput);
    // Clear the  input
    $('#input').val('');
    
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="story-input">text</div>
<input type="text" id="input" style="opacity: 1">

但是请注意,用户可以通过按住单个字符来绕过长度要求,因此检查 wordInput 的长度与 [= 的值的长度之和可能是明智的14=].

这是因为事件首先被触发并由您的代码处理,然后字符被添加到输入字段。这使得 $('#input').val() return 先前输入的字符。

您可以使用 String.fromCharCode(event.which),但这不会区分不同的大小写,您必须解析修饰键的事件对象并将字符转换为正确的大小写。


替代解决方案是使用 .keydown 像您现在一样处理特殊键,并使用 .keypress 处理字符键。原因是 .keypress 没有注册一些键,例如退格键。

这结合了 "best of both worlds",它会立即处理所有事件,您无需担心解析字符以使用正确的大小写。

使用此代码或查看 jsfiddle 上的(固定)示例。

$('#input').keydown(function(event) {
    var prevent = true;
    switch(event.which) {
        // Enter key
        case 13:    
            console.log('Submit');
        // Space key
        case 32:    
            console.log('Space disabled');
            break;
        // Backspace
        case 8:
            // Subscript the last char
            wordInput = wordInput.substr(0, wordInput.length - 1);
            break;
        // Any other key
        default:    
            prevent = false;
    }
    // Update the word displayed
    $('#story-input').html(wordInput);
    // Clear the  input
    $('#input').val('');

    // Stop event propagation, keypress will not be executed
    if(prevent)
        event.stopPropagation();
});

$('#input').keypress(function(event) {
    if (wordInput.length < 20) {
        wordInput += String.fromCharCode(event.which); // Add the typed letter
    }
    $('#story-input').html(wordInput);
});