对 keydown 事件使用 preventDefault() 后未触发事件 onchange

Event onchange not triggered after use preventDefault() on keydown event

提问人:Bruno Batista 提问时间:1/5/2023 最后编辑:Bruno Batista 更新时间:1/5/2023 访问量:288

问:

我有一个事件,我对输入进行了一些更改,并直接在代码中更改了值。为此,我需要使用 ,否则我单击的类型最终会在输入中重复。 我发现了一个类似的问题案例,我使用了与建议相同的解决方案,并且它起作用了:keydownpreventDefault()

preventdefault-in-a-keydown-event-onchange-event-not-trigger

$('.test').on('change', function(event) {
    console.log('## run change')
});

const symbolDecimal = '.';
const ignorables = [8, 9, 37, 38, 39, 40, 46, 109, 189];

$(".test").on('keydown', function(event) {
 const oldValue = event.target.value;
  // debugger;
  // Caso for alguma tecla alfabética sem estar segurando a tecla Control, ignora o comando
  const key = event.key;
  const $input = $(event.target);

  // Inibi alguns eventos especiais
  if (event.ctrlKey || (event.ctrlKey && (key.toLowerCase() === 'v' || key.toLowerCase() === 'a' )) ) {
    return;
  }

  // Captura precisão do input
  const precisao = 0;
  // Monta a regex para a máscara
  const mask = new RegExp("(\\-)?(\\d+)(\\d{"+precisao+"})$", 'g');

  // Captura posição inicial e final do cursos no input
  const start = $input.prop('selectionStart');
  const end = $input.prop('selectionEnd');
  // Distribui os caracteres do input em um buffer
  let arr = $input.val().split('');

  // Verifica se existe precisão e monta o retorno conforme é montado a regex
  let masked = '$1$2';
  if (precisao > 0)
    masked = '$1$2.$3';

  // Inicia o valor
  let value = $input.val();
  // Verifica se o número é negativo
  if (event.keyCode === 8 || event.keyCode === 46) {
    // Se for Backspace e o curso estiver na posição 0 do input só retornar
    if (event.keyCode === 8 && start === 0 && end === 0) return;

    // Calcula a diferença entre a área selecionada no Input
    let diff = start === end ? 1 : end - start;
    // Se não for área selecionada
    //     Se for Backspace, posiciona a remoção a um caractere anterior da posição do cursor
    //     Se for Delete, posiciona a remoção a um caractere posterior da posição do cursos
    let initStart = start === 0 ? 0 : start - 1;
    if (event.keyCode === 46) initStart = start;

    // Verifica se o caracter a ser removido simbolo decimal
    if (arr[initStart] === symbolDecimal) {
      initStart -= 1;
    }

    // Remove o(s) caracter(s) na posição que o selector está ou os valores selecionados
    arr.splice(initStart, diff);
    value = arr.join('');
    // Aplica a máscara no valor
    $input.val(value.replace(mask, masked));
    // Mantém o cursor na posição em que estava quando disparou evento de remoção
    $input[0].setSelectionRange(initStart, initStart);
  } else if (!isNaN(parseInt(key))) {
    // Adiciona novo número ao buffer
    arr.push(key);
    value = arr.join('');
    value = value.replace(mask, masked);
    // Aplica a máscara no valor

    $input.val(value);
  }
  // THIS PREVENTDEFAULT 
   event.preventDefault();
   
   // THE SOLUTION
   if (event.target.valueOnFocus === undefined) {
        event.target.valueOnFocus = oldValue;
        $(event.target).on('focus', function(event) {
            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://code.jquery.com/jquery-3.6.3.min.js"></script>
<input id="test" name="test" class="test">

如果我注释掉 THE SOLUTION 所在的部分,则事件将停止工作。如果我注释掉这个 THE SOLUTION 上方的 that,则该事件有效,但按下的类型在输入中似乎是重复的。onchangepreventDefault()onchange

我的问题与另一篇文章中提出的代码类似,但它已经很旧了,我还没有找到任何有更好解决方案或似乎正确的人。

我的问题是,为什么活动被取消了?为什么不使用 ,为什么该值会在 Input 中插入两次?我只测试了事件并且它有效,但它不适合我需要做的事情。onchangepreventDefault()onblur

javascript jquery 事件处理 dom-events

评论

0赞 Scott Marcus 1/5/2023
请在此问题中发布您要询问的代码。
0赞 Scott Marcus 1/5/2023
该事件由浏览器触发。通过代码对 DOM 元素值的更改不会触发事件。changechange
0赞 Bruno Batista 1/5/2023
我把我的代码放进去,它类似于另一个问题的链接,我找到了一个姑息性的解决方案。

答:

-1赞 Maria 1/5/2023 #1

我遇到了同样的问题,我发现的唯一决定是创建这样的函数:

function reload () {
  $("#myButton").unbind("click")
  $("#myButton").bind("click", function(event) {
    event.preventDefault()
  }) 
}

就是不行,我不知道为什么......preventDefault