Почему setTimeout (.., 0) срабатывает перед действием браузера в Firefox?Ошибка? - PullRequest
7 голосов
/ 25 июня 2019

У меня есть обработчик input.onkeydown, и я проверяю input.value после setTimeout(..0).

Я ожидаю, что input.value получит новое значение при выполнении обратного вызова setTimeout.

Во всех браузерах, кроме Firefox, это так. В Firefox это не всегда так.

Код для проверки:

<input id="input">
<script>
  input.onkeydown = function() {
    setTimeout(() => this.value = this.value.toUpperCase());
  };
</script>

Демо: http://plnkr.co/edit/rZmiHdttSXNdpKkR8YbH?p=preview

Поскольку вводимое значение вводится в верхнем регистре после setTimeout(..0), оно всегда должно быть в верхнем регистре. Но, как уже говорилось, в Firefox это не так.

Вот демонстрационное видео; первые несколько секунд демонстрируют проблему: https://jmp.sh/9XSROQ2

Соответствующая спецификация: https://dom.spec.whatwg.org/#concept-event-dispatch.

Я что-то не получаю, или это давняя ошибка в Firefox?

P.S. Если я добавлю console.log в setTimeout, я иногда вижу старое значение.

P.P.S. Цель этого вопроса - узнать, правильно ли я понимаю setTimeout или нет. Я знаком с множеством способов прописных букв input; пожалуйста, не предлагайте oninput, requestAnimationFrame или что-то подобное.

Ответы [ 2 ]

2 голосов
/ 25 июня 2019

Фактические характеристики здесь и фактически не определяют отношения между нажатием клавиши и изменением текущего значения входа .

Однако они читают, (подчеркните мое)

Для элементов ввода без определенного поведения активации ввода, но к которым применяются эти события, каждый раз, когда пользователь вызывает изменение значения элементабез явного действия фиксации пользовательский агент должен поставить в очередь задачу , чтобы запустить событие с именем input в элементе input, с атрибутом bubbles, инициализированным как true.Соответствующее событие изменения, если оно есть, будет запущено, когда элемент управления потеряет фокус.

Таким образом, фактически предполагается, что событие input (которое вы должны слушать в любом случае) должно запускаться асинхронно.Поскольку это событие является свидетельством изменения текущего значения , я не думаю, что поведение Firefox при применении изменений, вызванных событием Key в следующем цикле событий, вряд ли является ошибкой;помните, что браузеры должны вносить это изменение асинхронно после смерти события (и больше не может быть отменено любым обработчиком).

Некоторые дополнительные заметки (которые могут быть связаны с реальной причиной, кстати), ввод комбинированного символа (например, ^ + a => â) У меня 100% репродукция в FF на macO(потому что да, я подозреваю, что это также может быть связано с ОС).

Но, конечно, даже если это не идет вразрез с какими-либо спецификациями, и даже если у вас есть простое исправление (прослушайте событие ввода) вы все равно можете подать отчет об ошибке по крайней мере за то, что он не ведет себя, как другие поставщики.

0 голосов
/ 25 июня 2019

Я думаю, что это потому, что Firefox обрабатывает setTimeout (fn, 0) синхронно, также спрашивается здесь: Почему Firefox обрабатывает setTimeout (fn, 0) синхронно, а setTimeout (fn, 1) асинхронно?

Chrome и узел заменяют 0 на 1: Разница между setTimeout (fn, 0) и setTimeout (fn, 1)? Так что для них всегда асинхронно.Если вы запускаете его с setTimeout (fn, 1), он также работает в FF.

Если вы хотите синхронизировать его, используйте «oninput».Входное значение не обновляется полностью, когда происходит событие «onkeydown».Работа с таймаутом или без него в chrome / ff

input.oninput = function() {
    this.value = this.value.toUpperCase()
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...