Próbując rozwiązać ten problem samodzielnie, zauważyłem, że w rzeczywistości można zachować przewijanie strony i fokus danych wejściowych, wyłączając zmiany liczbowe, próbując ponownie uruchomić przechwycone zdarzenie na elemencie nadrzędnym, <input type="number"/>na którym zostało przechwycone , po prostu w ten sposób:
e.target.parentElement.dispatchEvent(e);
Jednak powoduje to błąd w konsoli przeglądarki i prawdopodobnie nie ma gwarancji, że będzie działać wszędzie (testowałem tylko w przeglądarce Firefox), ponieważ jest to celowo nieprawidłowy kod.
Innym rozwiązaniem, które działa ładnie przynajmniej na Firefoksie i Chromium, jest tymczasowe utworzenie <input>elementu w readOnlyten sposób:
function handleScroll(e) {
if (e.target.tagName.toLowerCase() === 'input'
&& (e.target.type === 'number')
&& (e.target === document.activeElement)
&& !e.target.readOnly
) {
e.target.readOnly = true;
setTimeout(function(el){ el.readOnly = false; }, 0, e.target);
}
}
document.addEventListener('wheel', function(e){ handleScroll(e); });
Jednym z efektów ubocznych, który zauważyłem, jest to, że może powodować migotanie pola na ułamek sekundy, jeśli masz inny styl readOnlypól, ale przynajmniej w moim przypadku nie wydaje się to stanowić problemu.
Podobnie (jak wyjaśniono w odpowiedzi Jamesa) zamiast modyfikować readOnlywłaściwość, można blur()pole, a następnie focus()przywrócić, ale znowu, w zależności od używanych stylów, może wystąpić migotanie.
Alternatywnie, jak wspomniano w innych komentarzach, możesz po prostu zadzwonić preventDefault()na wydarzenie. Zakładając, że obsługujesz wheelzdarzenia tylko na danych wejściowych liczbowych, które są w centrum uwagi i pod kursorem myszy (to właśnie oznaczają trzy powyższe warunki), negatywny wpływ na wrażenia użytkownika byłby bliski zeru.