принудительное перерисовывание DOM с помощью javascript по требованию
название вопроса выражает то, что я думаю, является окончательным вопросом, стоящим за моим конкретным случаем.
моем случае: Внутри обработчика щелчков я хочу сделать изображение видимым (анимация "загрузки") прямо перед запуском функции занятости. Затем я хочу сделать его невидимым снова после завершения функции. Вместо того, что я ожидал, я понимаю, что изображение никогда не становится видимым. Я предполагаю, что это связано с браузером, ожидающим завершения обработчика, прежде чем он сможет сделать что-либо перерисовка (я уверен, что для этого есть хорошие причины).
код (также в этой скрипке: http://jsfiddle.net/JLmh4/2/)
HTML-код:
<img id="kitty" src="http://placekitten.com/50/50" style="display:none">
<div><a href="#" id="enlace">click to see the cat</a> </div>
js:
$(document).ready(function(){
    $('#enlace').click(function(){
        var kitty = $('#kitty');
        kitty.css('display','block');
        // see: http://unixpapa.com/js/sleep.html
        function sleepStupidly(usec)
        {
            var endtime= new Date().getTime() + usec;
            while (new Date().getTime() < endtime)
                ;
        }
        // simulates bussy proccess, calling some function...
        sleepStupidly(4000);
        // when this triggers the img style do refresh!
        // but not before
        alert('now you do see it');
        kitty.css('display','none');
    });
});
я добавил alert звонок сразу после sleepStupidly функция, чтобы показать, что в этот момент отдыха браузер перерисовывается, но не раньше. Я невинно ожидал, что он перерисует сразу после установки "display" на "block";
для record, я также попытался добавить теги html или поменять местами классы css вместо изображения, отображаемого и скрываемого в этом коде. Результат тот же.
после всех моих исследований я думаю, что то, что мне нужно, это возможность заставить браузер перерисовывать и прекратить все остальное до тех пор.
возможно ли это? Возможно ли это в crossbrowser? Некоторые плагин я не смог найти может...?
я подумал, что, может быть, что-то вроде ' jQuery css callback' (как в этом вопросе:в JQuery можно ли получить функцию обратного вызова после установки нового правила css?) будет делать трюк ... но этого не существует.
Я также попытался разделить показ, вызов функции и скрытие в разных обработчиках для одного и того же события ... но ничего. Также добавление setTimeout для задержки выполнения функции (как рекомендуется здесь:принудительное обновление DOM в JavaScript).
спасибо и я надеюсь, что это также помогать другим.
Хавьера
EDIT (после установки моего предпочтительного ответа):
просто чтобы объяснить, почему я выбрал окно.стратегии через setTimeout. В моем реальном случае использования я понял, что для того, чтобы дать браузеру достаточно времени, чтобы перерисовать страницу, Я должен был дать ей около 1000 миллисекунд (гораздо больше, чем 50 для примера скрипки). Я считаю, что это связано с более глубоким деревом DOM (на самом деле, излишне глубоким). В функции setTimeout давайте подхода позволяет тебе это делать.
5 ответов
использовать window.setTimeout() С некоторой короткой незаметной задержкой для запуска медленной функции:
$(document).ready(function() {
    $('#enlace').click(function() {
        showImage();
        window.setTimeout(function() {
            sleepStupidly(4000);
            alert('now you do see it');
            hideImage();
        }, 50);
    });
});
Использовать JQuery show и hide обратные вызовы (или другой способ отображения чего-то вроде fadeIn/fadeOut).
$(document).ready(function () {
    $('#enlace').click(function () {
        var kitty = $('#kitty');
        // see: http://unixpapa.com/js/sleep.html
        function sleepStupidly(usec) {
            var endtime = new Date().getTime() + usec;
            while (new Date().getTime() < endtime);
        }
        kitty.show(function () {
            // simulates bussy proccess, calling some function...
            sleepStupidly(4000);
            // when this triggers the img style do refresh!
            // but not before
            alert('now you do see it');
            kitty.hide();
        });
    });
});
чтобы принудительно перерисовать, вы можете использовать offsetHeight или getComputedStyle().
var foo = window.getComputedStyle(el, null);
или
var bar = el.offsetHeight;
" el " является элементом DOM
Я не знаю, работает ли это в вашем случае (поскольку я его не тестировал), но при манипулировании CSS с JavaScript/jQuery иногда необходимо принудительно перерисовывать определенный элемент, чтобы изменения вступили в силу.
это делается путем простого запроса свойства CSS.
в вашем случае, я бы попробовал поставить kitty.position().left; перед вызовом функции до возни с setTimeout.
то, что сработало для меня, устанавливает следующее:
$(element).css('display','none'); 
после этого вы можете делать все, что захочешь, и в конечном итоге вы хотите сделать:
$(element).css('display','block');