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



我有一个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">

例子如果我注释掉解决方案的部分为,则onchange事件停止工作。如果我注释掉上面的preventDefault()解决方案onchange事件工作,但按下的类型在输入中出现重复。

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

我的问题是,为什么onchange事件被取消了?如果不使用preventDefault(),为什么要在输入中插入两次值?我只测试了onblur事件,它工作了,但它不适合我需要做的事情。

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

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

只是preventDefault不工作,我不知道为什么…

最新更新