每隔一段时间,Chrome会不正确地呈现完全有效的HTML/CSS或根本不呈现。深入DOM检查器通常足以让它意识到其方法的错误并正确地重新绘制,因此可以证明标记是好的。在我所从事的项目中,这种情况经常发生(并且可以预见),以至于我已经在某些情况下放置了代码来强制重绘。

这适用于大多数浏览器/操作系统组合:

    el.style.cssText += ';-webkit-transform:rotateZ(0deg)'
    el.offsetHeight
    el.style.cssText += ';-webkit-transform:none'

例如,调整一些未使用的CSS属性,然后要求一些强制重绘的信息,然后取消调整属性。不幸的是,Chrome for Mac背后的聪明团队似乎已经找到了一种方法,可以在不重新绘制的情况下获得这种offsetHeight。这样就杀死了一个有用的黑客。

到目前为止,为了在Chrome/Mac上获得同样的效果,我想出的最好的方法是:

    $(el).css("border", "solid 1px transparent");
    setTimeout(function()
    {
        $(el).css("border", "solid 0px transparent");
    }, 1000);

实际上,强制元素跳跃一点,然后冷却一秒钟,然后再跳回来。更糟糕的是,如果您将超时时间降低到500ms以下(到不太明显的地方),通常不会达到预期的效果,因为浏览器在恢复到原始状态之前不会重新绘制。

有人愿意提供一个更好的版本的重绘/刷新hack(最好基于上面的第一个例子),工作在Chrome/Mac?


当前回答

我有一个react组件列表,当滚动时,然后打开另一个页面,然后返回时,列表不会在Safari iOS上呈现,直到页面被滚动。这就是解决办法。

    componentDidMount() {
        setTimeout(() => {
            window.scrollBy(0, 0);
        }, 300);
    }

其他回答

不确定你到底想要达到什么目的,但这是我过去使用的一种方法,成功地迫使浏览器重新绘制,也许它对你有用。

// in jquery
$('#parentOfElementToBeRedrawn').hide().show(0);

// in plain js
document.getElementById('parentOfElementToBeRedrawn').style.display = 'none';
document.getElementById('parentOfElementToBeRedrawn').style.display = 'block';

如果这个简单的重画不工作,你可以试试这个。它在元素中插入一个空文本节点,以保证重绘。

var forceRedraw = function(element){

    if (!element) { return; }

    var n = document.createTextNode(' ');
    var disp = element.style.display;  // don't worry about previous display style

    element.appendChild(n);
    element.style.display = 'none';

    setTimeout(function(){
        element.style.display = disp;
        n.parentNode.removeChild(n);
    },20); // you can play with this timeout to make it as short as possible
}

编辑:在回应Šime Vidas,我们在这里实现的将是一个强制回流。你可以从大师本人http://paulirish.com/2011/dom-html5-css3-performance/找到更多信息

function resizeWindow(){
    var evt = document.createEvent('UIEvents');
    evt.initUIEvent('resize', true, false,window,0);
    window.dispatchEvent(evt); 
}

在500毫秒后调用这个函数。

Html:示例

<section id="parent">
  <article class="child"></article>
  <article class="child"></article>
</section>

Js:

  jQuery.fn.redraw = function() {
        return this.hide(0,function() {$(this).show(100);});
        // hide immediately and show with 100ms duration

    };

调用函数:

$ (' article.child ') .redraw ();/ / < = =坏主意

$('#parent').redraw();

我们最近遇到了这个问题,并发现使用translateZ将受影响的元素提升到复合层可以修复这个问题,而不需要额外的javascript。

.willnotrender { 
   transform: translateZ(0); 
}

由于这些绘画问题主要出现在Webkit/Blink中,而此修复主要针对Webkit/Blink,在某些情况下更可取。特别是因为许多JavaScript解决方案会导致回流和重绘,而不仅仅是重绘。

我也遇到过类似的问题,这一行JS代码帮我解决了问题:

document.getElementsByTagName('body')[0].focus();

在我的情况下,这是一个错误与Chrome扩展不重新绘制页面后改变其CSS从扩展。