按键按下事件的新值

16

浏览器:Google Chrome V19.0.1084.52

我有一个文本框,需要输入小于或等于255的数字,在按键按下时,我想检查该值是否大于或等于255,否则阻止事件。

在控制台中,当我对事件进行console.log时,它将显示event.srcElement.value作为将要出现的值,即从12 => 123,当我仅对 event.srcElement.value 进行console.log时,它将显示输入的内容,而不是将要出现的内容。

Console.log后面没有其他代码,也没有暂停。

如何在按键按下时找到文本框的新值,并为什么console.log返回不同的结果?

这是我的代码:

function inputNumeric(event,max) {

    console.log (event);
    console.log ('event.originalEvent.srcElement.value: '+event.originalEvent.srcElement.value);
    console.log ('event.srcElement.value: '+event.srcElement.value);

}

$("#rs485addr").keydown(function(event) {
    inputNumeric(event);
});

控制台输出:

event.originalEvent.srcElement.value: 12
event.srcElement.value: 12

event.srcElement:

accept: ""
accessKey: ""
align: ""
alt: ""
attributes: NamedNodeMap
autocomplete: ""
autofocus: false
baseURI: "http://10.50.50.60/controller/?bid=10"
checked: false
childElementCount: 0
childNodes: NodeList[0]
children: HTMLCollection[0]
classList: DOMTokenList
className: "width-60"
clientHeight: 18
clientLeft: 2
clientTop: 2
clientWidth: 62
contentEditable: "inherit"
dataset: DOMStringMap
defaultChecked: false
defaultValue: "1"
dir: ""
dirName: ""
disabled: false
draggable: false
files: null
firstChild: null
firstElementChild: null
form: null
formAction: ""
formEnctype: "application/x-www-form-urlencoded"
formMethod: "get"
formNoValidate: false
formTarget: ""
hidden: false
id: "rs485addr"
incremental: false
indeterminate: false
innerHTML: ""
innerText: ""
isContentEditable: false
jQuery17102950612970162183: 22
labels: NodeList[1]
lang: ""
lastChild: null
lastElementChild: null
localName: "input"
max: ""
maxLength: 3
min: ""
multiple: false
name: ""
namespaceURI: "http://www.w3.org/1999/xhtml"
nextElementSibling: null
nextSibling: Text
nodeName: "INPUT"
nodeType: 1
nodeValue: null
offsetHeight: 22
offsetLeft: 183
offsetParent: HTMLBodyElement
offsetTop: 365
offsetWidth: 66
onabort: null
onbeforecopy: null
onbeforecut: null
onbeforepaste: null
onblur: null
onchange: null
onclick: null
oncontextmenu: null
oncopy: null
oncut: null
ondblclick: null
ondrag: null
ondragend: null
ondragenter: null
ondragleave: null
ondragover: null
ondragstart: null
ondrop: null
onerror: null
onfocus: null
oninput: null
oninvalid: null
onkeydown: null
onkeypress: null
onkeyup: null
onload: null
onmousedown: null
onmousemove: null
onmouseout: null
onmouseover: null
onmouseup: null
onmousewheel: null
onpaste: null
onreset: null
onscroll: null
onsearch: null
onselect: null
onselectstart: null
onsubmit: null
onwebkitfullscreenchange: null
onwebkitfullscreenerror: null
onwebkitspeechchange: null
outerHTML: "<input class="width-60" id="rs485addr" maxlength="3" type="textbox" value="1">"
outerText: ""
ownerDocument: HTMLDocument
parentElement: HTMLSpanElement
parentNode: HTMLSpanElement
pattern: ""
placeholder: ""
prefix: null
previousElementSibling: HTMLLabelElement
previousSibling: Text
readOnly: false
required: false
scrollHeight: 16
scrollLeft: 0
scrollTop: 0
scrollWidth: 60
selectionDirection: "forward"
selectionEnd: 3
selectionStart: 3
size: 20
spellcheck: true
src: ""
step: ""
style: CSSStyleDeclaration
tabIndex: 0
tagName: "INPUT"
textContent: ""
title: ""
translate: true
type: "text"
useMap: ""
validationMessage: ""
validity: ValidityState
value: "123"
valueAsDate: null
valueAsNumber: NaN
webkitGrammar: false
webkitRegionOverflow: "undefined"
webkitSpeech: false
webkitdirectory: false
webkitdropzone: ""
willValidate: true

嗯,不应该有任何差异。一个 jsFiddle 会很有帮助..! - Willem Mulder
6个回答

36
我不确定以下内容是否有所帮助,但在事件监听器中,当我遇到类似情况时,我使用了一个1毫秒延迟的setTimeout()函数,在此处执行主要功能以检查值等。
这是因为当触发keydown事件时,输入字段还没有填充新数据。
简单的jQuery示例:
$('#input').on('keydown', function(e) {
  var field = $(this);
  var prevValue = field.val();
  setTimeout(function() {
    // check if new value is more or equal to 255
    if (field.val() >= 255) {
      // fill with previous value
      field.val(prevValue);
    }

  }, 1);
});

更新

在现代浏览器中使用 'input' 事件。

var prevValue = 0;
$('#input').on('input', function(e) {
  var field = $(this);
  // check if new value is more or equal to 255
  if (field.val() >= 255) {
    // fill with previous value
    field.val(prevValue);
  } else {
    // If value is lower than 255 set it in prev value.
    prevValue = field.val();
  }
});

1
@WilliamIsted:我非常确定你不想要一个超时解决方案。 - Bergi
谢谢@Kane,我花了几个小时搜索类似的东西。这个完美地解决了我的问题! - yourdeveloperfriend
@HerrWalter,您应该在现代浏览器中使用“input”事件。 Keyup不是一个理想的事件,因为它只会在按键松开时触发一次。但是如果用户按住一个键怎么办?在这种情况下,在输入事件可用之前,您必须坚持使用keydown。 - Kane Cohen
1
field.val()如何既等于先前的值又等于新值? - Petrus Theron
1
var prevValue = field.val(); 后面跟着 if (field.val() >= ...) ...,这相当于 if (prevValue >= 255) ... - Petrus Theron
显示剩余5条评论

12
你不应该使用 keydown,而应该使用 keypress。这样你将接收到待输入字符的实际字符代码。
请查看“事件后输入框的键码、keydown、keyup值”http://www.quirksmode.org/dom/events/keys.html,尤其是 http://www.quirksmode.org/js/keys.html
inputElement.addEventListener("keypress", function(e) {
     var curval = e.srcElement.value;
     var newchar = String.fromCharCode(e.charCode || e.keyCode);
     if (/* condition */)
         e.preventDefault();
}, false);
如果您只想在输入后获取输入值,您需要使用keyup事件。

7
keypress和keyup事件不允许你“取消”按键事件。 - Trevor
按键事件也会在Firefox中触发,如果我按下退格键,这可能不是你想要的。 - Pieter
3
Keypress事件现已被弃用:https://developer.mozilla.org/en-US/docs/Web/API/Element/keypress_event。 input事件是更好的替代方案-https://caniuse.com/#feat=input-event。 - stwr667
keyup 事件是你想要的,它可以在你输入字段时获取最新的值。 - eyal_katz
2
最好使用input事件,它适用于任何输入方法,而不仅仅是打字。@eyal_katz - Bergi
显示剩余3条评论

1

由于这是在搜索“如何在输入键按下时获取新值”时出现的第一个结果,因此我在此发布一个有效的答案。

这对于许多情况应该足够了,但我建议检查“keyup”或“input”或任何其他事件是否更适合您的个人问题。

function getNewInputValue(e) {
      let newValue = e.target.value;
      let valueArray = newValue.split('');
      const selectionLength = (e.target.selectionEnd - e.target.selectionStart);
      if (e.key === 'Backspace') {
        if (selectionLength === 0 && e.target.selectionStart > 0) {
          valueArray.splice(e.target.selectionStart - 1, selectionLength + 1);
        } else {
          valueArray.splice(e.target.selectionStart, selectionLength);
        }
      } else if (e.key === 'Delete') {
        if (selectionLength === 0) {
          valueArray.splice(e.target.selectionStart, selectionLength + 1);
        } else {
          valueArray.splice(e.target.selectionStart, selectionLength);
        }
      } else {
        valueArray.splice(e.target.selectionStart, selectionLength, e.key);
      }
      newValue = valueArray.join('');
      return newValue;
}

如果您使用此代码片段来防止输入,如果新值不符合您的条件,则还应考虑在触发某些“生活质量”功能时不进行检查,例如使用箭头键在输入内导航,或通过按Tab键导航到下一个控件。

这些是我忽略的键:

const ignoredKeys = [
    'ArrowLeft',
    'ArrowRight',
    'Tab',
    'End',
    'Home',
    'ArrowUp',
    'ArrowDown',
  ];


这是唯一一个真正解决问题的方案。我不明白为什么它没有得到投票(除了年龄)。我遇到了这样的情况,输入必须具有特定的校验和,我需要拒绝任何会违反校验和的字符,无论在字符串中的哪个位置输入。使用超时似乎对于现代使用来说太过简陋。 - Octabode

0
简单的解决方案:只需使用 keyup 事件(而不是 keydown 事件)即可。 这将为您提供用户输入最新字符后的最新值。 这样就解决了问题。

0

我能想到的唯一解释是,在控制台中输出的 srcElement 对象仍然与事件对象关联,即使在键盘按下事件后也是如此。所以,即使已经在控制台中,该对象也从 12 更新为 123。

直接输出 event.srcElement.value 不会出现这种情况,因为它是一个文字值,在记录时被复制而不是引用...

如果你非常快捷,你可以在控制台中观察到它从 12 变为 123 的变化;-)


0

在 @Bergi 的评论基础上添加,以便包含文本选择和光标位置,可以按照以下方式进行:

inputElement.addEventListener("keypress", (event) => {
    let curval = event.srcElement.value;
    let newchar = String.fromCharCode(event.charCode || event.keyCode);
    let curval_arr = curval.split("");
    curval_arr.splice(event.target.selectionStart, (event.target.selectionEnd - event.target.selectionStart), newchar);
    let newval = curval_arr.join("");

    //TODO: your logic here with "newval" containing the value to be.
    //console.log(curval, newchar, newval);
    //event.preventDefault();
}, false);

除了用户按退格键或删除键时会出现添加字符而不是减少字符的问题外,它工作得还可以。 - Phil M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接