Задать вопрос
@Luhashan

Почему transitionend не срабатывает и что конкретно происходит при изменении в DOM дереве?

Есть очень тривиальный код, который работает как и ожидается:
<!DOCTYPE html>
<html>
<head>
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <style type="text/css">
    	.opacity {
    		opacity: 0;
    	}
    </style>
</head>
<body>
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div id="move" style="transition-duration: 1s;">4</div>
    <script>
    $(document).ready(function() {
        function on_transitionend(event) {
        	$(this).toggleClass('opacity');
        }
        $('div').on('transitionend webkitTransitionEnd oTransitionEnd', on_transitionend);
        $('#move').toggleClass('opacity');
    });
    </script>
</body>
</html>

Но, если в обработчике on_transitionend() осуществить перестановку элемента, то его свойство transition-duration перестает работать, соответственно, не происходит и вызов обработчика:
function on_transitionend(event) {
        	$(this).insertBefore($('div').get(0));
        	$(this).toggleClass('opacity');
        }

При этом, в браузере видно, что все свойства и обработчики элемента, который был перестановлен на месте.
Если же после перестановки элемента попытаться вызвать обработчик transitionend не из основного потока а через setTimeout, то все работает как и ожидается:
function on_transitionend(event) {
        	$(this).insertBefore($('div').get(0));
        	var el = this
        	setTimeout(function() {$(el).toggleClass('opacity');}, 0);
        }

Соответственно вопрос, почему так происходит и что именно происходит после изменения DOM дерева?
У меня есть лишь одна гипотеза: при изменении DOM дерева срабатывает апишное событие, которые помещается в очередь событий с наивысшим приоритетом. Соответственно, после завершения основного потока оно срабатывает и производит некий "ремаппинг" всего DOM дерева, включая обработчики и свойства. После этого нулевой таймаут срабатывает и все ОК. Если так, то можно ли вызвать этот "ремаппинг" вызвать из js кода?
Заранее большое спасибо за пояснения!
  • Вопрос задан
  • 369 просмотров
Подписаться 1 Сложный 2 комментария
Решения вопроса 1
@alekcena
Нелинейный наставник
гипотеза: при изменении DOM дерева срабатывает апишное событие, которые помещается в очередь событий с наивысшим приоритетом. Соответственно, после завершения основного потока оно срабатывает и производит некий "ремаппинг" всего DOM дерева, включая обработчики и свойства.

Это 100% не так. Я даже не понял что вы написали.

Тк как у нас 2 действия связанных с отрисовкой они оптимизируются. Именно по этому все действия с визуализацией делают как можно ближе. В вашем случае. Вы делаете перестановку дом ноды. Это вызывает перерисовку элементов. Она видит "Ага ещё и класс меняем -> сразу его меняем -> а потом рисует дом". Тк как она рисует уже с применёнными эффектами - событие не срабатывает.

Почему с таймером работает. Думаю становится понятно.
Рисуем дом->Таймер независимо срабатывает и навешивает класс->Рисуем ещё раз. Событие происходит.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы