我可以使用javascript强制浏览器“刷新”任何挂起的布局更改吗?

时间:2011-08-05 12:01:23

标签: javascript dom layout browser

我有一个使用Javascript构建UI的库,由于涉及动态内容,我有时希望将内容放到浏览器中,检查布局如何更改以支持这一点,然后根据结果执行不同的逻辑。例如:检测某些文本是否溢出并使用省略号截断它。

通常我通过发布更改来实现它,然后使用window.setTimeout(0)等待布局更新并调用其余的逻辑。这显然是次优的,因为不同的浏览器可能实现的最小超时太慢而不能防止使用大量CPU的闪烁或更快。

理想情况下,我想进行DOM更改,然后强制布局同步更新并立即内联运行“修复”逻辑。有什么想法吗?

4 个答案:

答案 0 :(得分:6)

我的理解是,读取任何CSS属性都会强制重排。您根本不需要setTimeout

摘自Rendering: repaint, reflow/relayout, restyle

  

但有时脚本可能会阻止浏览器优化回流,并使其刷新队列并执行所有批量更改。当您请求样式信息时会发生这种情况,例如

 offsetTop, offsetLeft, offsetWidth, offsetHeight
 scrollTop/Left/Width/Height
 clientTop/Left/Width/Height
 getComputedStyle(), or currentStyle in IE
     

以上所有这些都基本上是在请求有关节点的样式信息,而且只要您这样做,浏览器就必须为您提供最新的值。为此,它需要应用所有计划的更改,刷新队列,咬住子弹并进行重排。

Here's a list of the API calls/properties that will trigger a reflow

答案 1 :(得分:3)

我们遇到了IE8的疯狂问题(Firefox,Chrome很好)。我们在子元素上使用toggleClass('enoMyAddressesHide')。

.enoMyAddressesHide{display:none}

但是,父(s)div容器不会刷新/重新布置其高度。

setTimeout(),读取位置,读取元素的宽度和高度没有帮助。 最后,我们可以找到一个有效的解决方案:

jQuery(document).ready(function ($) {
    var RefreshIE8Layout = function () {
        $('.enoAddressBook:first').css('height', 'auto');
        var height = $('.enoAddressBook:first').height();
        $('.enoAddressBook:first').css('height', height);
    };

    $(".enoRowAddressInfo .enoRowAddressInfoArea ul li img.enoMyAddresses").click(function () {
        $(this).parent().find(".enoAllInfoInAddressBox,img.enoMyAddresses").toggleClass('enoMyAddressesHide');

        RefreshIE8Layout(); // fix IE8 bug, not refresh the DOM dimension after using jQuery to manipulate DOM
    });
});

它看起来很愚蠢,但它确实有效!

答案 2 :(得分:0)

我不知道这实际上对您的实现有效,但是:

var myDiv = document.getElementById("myDiv");
myDiv.innerHTML = "".concat(myDiv.innerHTML);

我认为设置innerHTML会强制对子元素进行DOM重新加载。我不知道如果你把它放到整个网站会发生什么。听起来好像你已经很好地连接到了整个DOM,并且这个方法可能会强制你已经做过的任何节点引用都变得不确定。换句话说:

var mySelect = document.getElementById("mySelect");// suppose this lives in myDiv.
var myDiv = document.getElementById("myDiv");
myDiv.innerHTML = "".concat(myDiv.innerHTML);

在上面的例子中,我相信你会失去对mySelect的引用。如果你有很多这样的事情,并且你使用的字段不是getter(即,每次访问时都没有得到每个使用$()或$ get或document.getElementById(..)的元素,那么这种潮红很有可能让你感到困扰。

您肯定会丢失任何您未手动跟踪/设置的页面状态数据 - 来自用户的新文本的文本框,用户新检查的复选框等,将使用此方法重新初始化为其默认状态潮红。

祝你好运 - 编码愉快!

答案 3 :(得分:0)

是的,你可以!!

大多数浏览器通过对更改进行排队并批量执行来优化重排过程。刷新渲染树更改需要您检索一些布局信息(偏移计算,getComputedStyle()和滚动值)。

var el = document.getElementById("my-element");
var top = el.offsetTop;

上述代码将强制浏览器在渲染队列中执行更改,以便返回正确的值。

简单!!