【问题标题】:preventDefault() in a keydown event, onchange event not triggerpreventDefault() 在 keydown 事件中,onchange 事件不会触发
【发布时间】:2017-10-19 08:24:32
【问题描述】:

在以编程方式更改值的 keydown 或 keypress 事件中调用的 preventDefault() 不会考虑更改,也不会在输入文本退出时触发 onchange 事件。

示例代码:

$('#textbox1').on('change', function() {
    alert('onchange called');
});

$('#textbox1').on('keydown', function(event) {
    if(event.key=='a') {

      $(this).val('A');
      //event.target.value = 'A';
      event.preventDefault();
    }
});

在调用 onchange(保留输入文本)后,仅输入 char 'a' 并再次保留输入。

小提琴代码:http://jsfiddle.net/gxx5744s/1/

什么是使用 onchange 事件来检查值是否已更改?一对旧/新值变量?一个布尔值? 可以和它互动吗?

Keydown 事件默认也可能这样做。

【问题讨论】:

  • 我猜触发onchange 是您正在阻止的default 的一部分。顺便问一下,你的问题是什么?您想知道如何在您的操作之后手动触发 onchange 吗?
  • 如果我手动触发 onchange 事件,它每次都会被调用,而不仅仅是当我离开输入焦点并改变值时。

标签: javascript onchange keypress keydown preventdefault


【解决方案1】:

来自the docs:

根据要更改的表单元素的类型以及用户与元素交互的方式,更改事件会以不同的方式触发 时刻:

  • 当元素在其值更改后失去焦点时,但不是 已提交(例如,在编辑 &lt;textarea&gt; 或 <input type="text"> 的值之后)。

在您的示例中就是这种情况。

尝试更改值并取消焦点,您会看到警报。

【讨论】:

  • 这不是重点!当文本输入失去焦点时触发该事件,但不是在调用函数的“a”之后触发,但它也应该被触发,阻止默认值不应该阻止......
  • 您的方式可行,但是当您将事件更改为“模糊”而不是“更改”时,它会在每次输入松散焦点时触发,不仅在值更改之后!!!
  • 事实上,情况比示例更复杂,在 onchange 事件上我必须调用服务器端的侦听器。我想避免在 blur 事件上调用它,而只在 onchange 事件上调用它。我确认使用 blur 事件是一个很好的解决方案,但也是一种解决方法。
【解决方案2】:

onchange 事件通常在您更改文本输入的值时触发,然后它失去焦点,就像这里的情况一样......但是当调用具有 preventDefault 的函数时,它不会被触发,这不是预期的行为!!!

preventDefault 应该防止调用它的 keydown 事件的默认行为,而不是 onchange 事件的默认行为,这实际上是无法取消的......

我想问题是不同的:

该值的默认设置似乎与JQuery方式不同

$(this).val('A');

可能是因为只更改了提交的值而不是 DOM 元素...如果您将此行更改为

$(this).attr('Value','A');

它的行为符合预期!

有趣的是,默认行为是不设置属性值,两种方式也改变显示,但一定有区别!

编辑:对我来说,@Kaddath 的解决方案似乎是最合适的:

var change = false;

$('#textbox1').on('change', function() {
  alert('onchange called');
});

$('#textbox1').on('blur', function() {
  if (change) {
    alert('"onchange" called too');
    change = false;
  }
});

$('#textbox1').on('keydown', function(event) {
  if (event.key == 'a') {
    $(this).val('A');
    change = true;
    event.preventDefault();
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="textbox1" />

【讨论】:

  • 现在这很有趣,绝对值得记住!查看文档后,我可以确认:“使用此方法(或使用本机 value 属性)设置值不会导致更改事件的调度。因此,相关的事件处理程序将不会被执行。如果你要执行它们,您应该在设置值后调用 .trigger("change")。 (from the docs)
  • 属性值仅用于在第一次显示输入文本时预设值。不适用于修改显示值。
  • 对于 Kaddath:如果我手动触发 onchange 事件,它每次都会被调用,而不仅仅是当我离开输入焦点并更改值时。
  • @Gian 是的,当然触发它会立即生效。您可以做的是创建一个状态变量来记住发生了变化,并在您的元素上实现blur 函数。在 blur 函数中,检查状态,如果需要,触发更改,然后清除状态 var。 (编辑:可能有一种方法可以“通知”没有模糊的变化,但我不知道)
  • 事实上,实际情况要复杂一些,我需要做的是一个通用函数,如果需要,可以在某些可能还带有 onchange 事件的文本输入上应用。将 blur 事件与变量挂钩是一个很好的解决方案,但也可能会发生 onchange 被调用 2 次:一次来自 blur,一次来自输入文本。
【解决方案3】:

采用@Kaddath 的想法,修改后的解决方案有点“肮脏”,但可能会奏效。 我不太喜欢,但目前我没有发现它更好。

$('#textbox1').on('change', function() {
	alert('onchange called');
});
    
$('#textbox1').on('keydown', function(event) {    
  var oldValue = event.target.value;
  
  if (event.keyCode == 46) { //DELETE
  	event.target.value = ""
    } else
		event.target.value = event.key + event.target.value;
    
  event.preventDefault();

  if (event.target.valueOnFocus === undefined) {
    // set a new property on the input element
    event.target.valueOnFocus = oldValue;
    
    $(event.target).on('focus', function(event) {
      // From the second time that enter on the input element,
      // update the new property
      event.target.valueOnFocus = event.target.value;
    });
    
   $(event.target).on('blur', function(event) {
      if (event.target.value !== event.target.valueOnFocus)
        $(event.target).trigger('change');
  	});
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="textbox1" />

小提琴:http://jsfiddle.net/gxx5744s/3/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    • 2011-06-14
    • 1970-01-01
    • 2016-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多