使用javascript按需强制DOM重绘

时间:2013-06-01 18:08:08

标签: javascript jquery dom

问题的标题表达了我认为是我的具体案例背后的最终问题。

我的情况: 在单击处理程序中,我想在繁忙的函数启动之前使图像可见(“加载”动画)。然后我想在函数完成后再次使它不可见。 而不是我所期望的,我意识到图像永远不会变得可见。我猜这是因为浏览器等待处理程序结束,然后才能进行任何重绘(我相信这有很好的性能原因)。

代码(也在这个小提琴中: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'之后重新绘制;

为了记录,我还尝试了附加html标签或交换css类,而不是显示和隐藏在此代码中的图像。结果相同。

在我完成所有研究后,我认为我需要的是强制浏览器重绘并在此之前停止其他所有事情的能力。

有可能吗?是否有可能以交叉浏览器的方式进行?一些我无法找到的插件......?

我认为这可能类似于'jquery css callback'(如在这个问题:In JQuery, Is it possible to get callback function after setting new css rule?中)会做的伎俩...但这不存在。

我还试图将显示,函数调用和隐藏在同一事件的不同处理程序中...但没有。同时添加setTimeout以延迟函数的执行(按照此处的建议:Force DOM refresh in JavaScript)。

谢谢,我希望它也有助于其他人。

哈维尔

编辑(在设置我的首选答案后):

只是为了进一步解释为什么我选择了window.setTimeout策略。 在我的实际用例中,我已经意识到为了给浏览器足够的时间来重绘页面,我不得不给它大约1000毫秒(比小提琴例子的50多)。我认为这是由于更深层次的DOM树(实际上是不必要的深层)。 使用setTimeout let方法可以做到这一点。

5 个答案:

答案 0 :(得分:7)

使用JQuery showhide回调(或以其他方式显示fadeIn / fadeOut等内容)。

http://jsfiddle.net/JLmh4/3/

$(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();
        });
    });
});

答案 1 :(得分:5)

使用window.setTimeout()使用一些短暂的无法察觉的延迟来运行慢速功能:

$(document).ready(function() {
    $('#enlace').click(function() {
        showImage();

        window.setTimeout(function() {
            sleepStupidly(4000);
            alert('now you do see it');
            hideImage();
        }, 50);
    });
});

Live demo

答案 2 :(得分:2)

要强制重绘,可以使用offsetHeight或getComputedStyle()。

var foo = window.getComputedStyle(el, null);

var bar = el.offsetHeight;

&#34; EL&#34;是一个DOM元素

答案 3 :(得分:0)

我不知道这是否适用于您的情况(因为我没有测试过),但是当使用JavaScript / jQuery操作CSS时,有时需要强制重绘特定元素以使更改生效。

这可以通过简单地请求CSS属性来完成。

在你的情况下,在尝试使用kitty.position().left;之前,我会尝试在函数调用之前添加setTimeout

答案 4 :(得分:0)

对我有用的是设置以下内容:

$(element).css('display','none'); 

之后你可以做任何你想做的事,最终你想做:

$(element).css('display','block');