繁体   English   中英

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

[英]Can I use javascript to force the browser to “flush” any pending layout changes?

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

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

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

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

渲染摘录:重绘、回流/重新布局、重新样式

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

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

以上所有这些本质上都是请求有关节点的样式信息,并且无论何时执行此操作,浏览器都必须为您提供最新的值。 为此,它需要应用所有计划的更改,刷新队列,咬紧牙关并进行回流。

这是将触发 reflow 的 API 调用/属性列表

(这个答案曾经链接到一个现在 404 的网站。 这是回程机中的一个链接。)

我们在 IE8 上遇到了一个疯狂的问题(Firefox、Chrome 都可以)。 我们在子元素上使用 toggleClass('enoMyAddressesHide') 。

.enoMyAddressesHide{display:none}

但是父 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
    });
});

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

是的你可以!!

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

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

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

简单的!!

我不知道这实际上适用于您的实施,但是:

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(..) 获取你关心的每个元素)然后这种类型的冲洗很有可能会让你失望。

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

祝你好运 - 编码愉快!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM