jquery 在按键事件上使用preventDefault()后未触发事件onchange

xyhw6mcr  于 2023-01-08  发布在  jQuery
关注(0)|答案(1)|浏览(199)

我有一个keydown事件,我对输入做了一些更改,并直接在代码中更改了值。要使其工作,我需要使用preventDefault(),否则我单击的类型最终会在输入中重复。我发现了一个与此问题类似的案例,我使用了建议的相同解决方案,它工作了:
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">

example
如果注解掉THE SOLUTION所在的部分,onchange事件将停止工作;如果注解掉THE SOLUTION上方的preventDefault()onchange事件将工作,但按下的类型在输入中出现重复。
我的问题与这篇文章中提出的代码类似,但它已经很旧了,我还没有找到任何人有更好的解决方案或似乎是正确的。
我的问题是,为什么onchange事件被取消了?为什么,如果你不使用preventDefault(),这个值在输入中插入了两次?我只测试了onblur事件,它工作了,但是它不适合我需要做的事情。

nsc4cvqm

nsc4cvqm1#

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

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

只是preventDefault不起作用,我不知道为什么...

相关问题