ты пишешь в коде, друг за дружкой. Когда стек опустошается (нет очереди выполнения) - становится возможным поместить в этот стек вещи, которые были запланированы для выполнения - например, отрисовка анимации или вызов обработчика аякс-запроса. Это называется асинхронность. Ты забиваешь стек синхронными функциями и вызовами - обычными, например, добавлением и удалением класса - если среди этих операций и вызовов есть setTimeout, setInterval, ajax - выполнение соответствующих колбэков не кладётся в текущий стек, иначе это помешало бы выполнять следующие команды, оно помещается в очередь колбэков.
Когда твой стек обычных вызовов пустой и если пришло время выполнить колбэк - этот колбэк из очереди колбэков вытаскивается в стек и выполняется. Стек опять пуст - повторяем цикл. И так далее.
Запуск анимации - это вообще операция как бы браузерного рендера. Она выполяется как минимум асинхронно после очистки стека, а как максимум - ещё хитрее, перед каждым вытаскиванием колбэка из очереди колбэков в стек, браузер позволяет себе сделать один кадр отрисовки - и только потом вытаскивает колбэк из очереди в стек выполнения. Это позволяет не подвешивать отрисовку намертво, если попадётся длинная очередь колбэков, так как мы не ждём выполнения всех из них, а впихиваем между ними кадр отрисовки
Так вот
Когда ты делаешь
element.addClass('class')
element.removeClass('class')
Ты делаешь две операции синхронно, друг за другом. После этих операций выполняется весь твой остальной код, и только потом запускается тот самый кадр отрисовки. Что видит движок отрисовки браузера? В прошлый раз у элемента был класс class, и сейчас класс тоже на месте, следовательно, анимировать ничего не нужно
Как с этим справиться?
Заставить браузер сделать так, чтобы на одном шаге отрисовки он увидел, что класс есть, а на следующем - что его нет (или наоборот, или не класса а стиль, не важно)
Как этого добиться? Использовать requestAnimationFrame, который запланирует выполнение на этапе как раз отрисовки.
requestAnimationFrame(()=>{
// Выполни на следующем шаге:
removeClass();
requestAnimationFrame(()=>{
// И запланируй на следущий
addClass()
})
})
Ответил как батя
ну, вообще да. теперь всё понятно, спасибо, только мне кажется. что не всё так просто с этим стеком. навешивать транзишн через фпс действительно куда более логично p.s. я всё таки поправлю, что ты исказил чутка ТЗ, в оригинале просто вставляется нода в дерево и на неё уже после навешивается класс
кстати, условие описанное тобой не отрабатывается
Обсуждают сегодня