Когда вы вносите изменения в dom, например classList.remove('anim')
, это может привести к каскаду изменений на странице. Рендеринг этих изменений может быть дорогостоящим, и, поскольку довольно часто вы меняете несколько вещей подряд, браузеры пытаются группировать накопленные изменения и выполнять вычисления только в конце того, что вы делаете.
Так что, если этой странной строки не было, вот что произойдет:
- Вы удалите класс. Браузер замечает это, но пока не перерисовывает экран
- Вы добавляете класс. Браузер отмечает это, но пока не перерисовывает экран
- Ваша функция завершается, и браузер решает выполнить необходимые вычисления, чтобы страница соответствовала тому, что вы просили ... но ничего не изменилось ! Вы вернули страницу в то же состояние, в котором находились до запуска обработчика кликов. Поскольку ничего не изменилось, дисплей остается прежним; анимация не запускается.
То, что делает эта дополнительная строка кода, просит браузер предоставить вам информацию о домене. Но чтобы узнать, что такое offsetWidth, браузер должен отказаться от плана пакетирования изменений и выполнить переформатирование страницы прямо сейчас. В текущем состоянии нет класса run-animation, что является изменением, поэтому анимация сбрасывается. А позже, когда функция завершает свою работу, она снова выполняет вычисления и видит, что вы сделали еще одно изменение по сравнению с тем, когда оно предоставило вам offsetWidth, поэтому оно также применяет это.
Короче говоря: вы ' вынуждаете браузер выполнять дополнительную работу, и так уж бывает, что в этом случае это желательно. В большинстве случаев принуждать браузер выполнять дополнительную работу - это плохо. Большую часть времени вы хотите избегать запросов к dom таким образом, поскольку это может снизить производительность.
Другой способ заставить это работать - удалить класс сейчас, а затем добавить класс на короткое время. позже, как в:
element.addEventListener("click", function(e){
element.classList.remove("anim");
setTimeout(() => element.classList.add("anim"), 0);
}, false);