简体   繁体   English

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

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

I have a library that build UI using Javascript, and because of the dynamic content involved I sometimes want to put content out to the browser, examine how the layout was changed to support this and then do a different logic depending on the result.我有一个使用 Javascript 构建 UI 的库,由于涉及到动态内容,我有时想将内容放到浏览器中,检查如何更改布局以支持这一点,然后根据结果执行不同的逻辑。 For example: detect if some text is overflowing and truncate it with an ellipsis.例如:检测某些文本是否溢出并用省略号截断它。

Usually I implement this by putting out the changes, then using window.setTimeout(0) to wait for the layout to update and invoke the rest of the logic.通常我通过发布更改来实现这一点,然后使用 window.setTimeout(0) 等待布局更新并调用其余的逻辑。 This is obviously sub-optimal as different browsers may either implement a minimal timeout that is too slow to prevent flicker or faster that uses a lot of CPU.这显然是次优的,因为不同的浏览器可能会实现一个太慢而无法防止闪烁的最小超时,或者更快地使用大量 CPU。

Ideally I would like to do the DOM changes, then force the layout to update synchronously and run the "fix-up" logic immediately inline.理想情况下,我想做 DOM 更改,然后强制布局同步更新并立即内联运行“修复”逻辑。 Any ideas?有任何想法吗?

My understanding is that reading any of the CSS properties will force a reflow.我的理解是读取任何 CSS 属性都会强制重排。 You should not need to setTimeout at all.您根本不需要setTimeout

Excerpt fromRendering: repaint, reflow/relayout, restyle : 渲染摘录:重绘、回流/重新布局、重新样式

But sometimes the script may prevent the browser from optimizing the reflows, and cause it to flush the queue and perform all batched changes.但有时脚本可能会阻止浏览器优化回流,并导致它刷新队列并执行所有批量更改。 This happens when you request style information, such as当您请求样式信息时会发生这种情况,例如

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

All of these above are essentially requesting style information about a node, and any time you do it, the browser has to give you the most up-to-date value.以上所有这些本质上都是请求有关节点的样式信息,并且无论何时执行此操作,浏览器都必须为您提供最新的值。 In order to do so, it needs to apply all scheduled changes, flush the queue, bite the bullet and do the reflow.为此,它需要应用所有计划的更改,刷新队列,咬紧牙关并进行回流。

Here's a list of the API calls/properties that will trigger a reflow .这是将触发 reflow 的 API 调用/属性列表

(This answer used to link to a site that 404s now. Here's a link to it in the wayback machine .) (这个答案曾经链接到一个现在 404 的网站。 这是回程机中的一个链接。)

We encountered a crazy problem with IE8 (Firefox, Chrome are fine).我们在 IE8 上遇到了一个疯狂的问题(Firefox、Chrome 都可以)。 We use toggleClass('enoMyAddressesHide') on child element.我们在子元素上使用 toggleClass('enoMyAddressesHide') 。

.enoMyAddressesHide{display:none}

But the parent(s) div container does not refresh/re-layout its height.但是父 div 容器不会刷新/重新布局其高度。

setTimeout(), read position, read width and height of element do not help. setTimeout()、读取位置、读取元素的宽度和高度没有帮助。 Finally we can find out a working solution:最后我们可以找到一个可行的解决方案:

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

It looks stupid, but it works!它看起来很愚蠢,但它有效!

Yes, you can!!是的你可以!!

Most browsers optimize the reflow process by queuing changes and performing them in batches.大多数浏览器通过将更改排队并批量执行来优化回流过程。 Flushing the render tree changes requires you to retrieve some layout information ( offset calculations, getComputedStyle(), and scroll values ).刷新渲染树更改需要您检索一些布局信息(偏移计算、getComputedStyle() 和滚动值)。

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

The above code will force the browser to execute changes in rendering queue in order to return the correct values.上面的代码将强制浏览器在渲染队列中执行更改以返回正确的值。

Simple!!简单的!!

I have no idea that this will actually work for your implementation, but:我不知道这实际上适用于您的实施,但是:

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

I believe that setting innerHTML forces a DOM reload for a child element.我相信设置 innerHTML 会强制为子元素重新加载 DOM。 I have no idea what would happen if you scoped this to the whole site.我不知道如果你把这个范围限定到整个网站会发生什么。 It sounds like you're pretty well hooked into the DOM all over the place though, and this method might force any node references you've already made to become undefined.听起来您已经很好地融入了 DOM,但这种方法可能会强制您已经创建的任何节点引用变为未定义。 In other words:换句话说:

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

In the above instance, I believe you'll lose your reference to mySelect.在上面的例子中,我相信你会失去对 mySelect 的引用。 If you've got lots of this going on and you're using fields not getters (ie, not getting each element you care about using $() or $get or document.getElementById(..) every time you access it) then there's a strong chance this type of flushing could hose you.如果你有很多这样的事情发生并且你使用的是字段而不是 getter(即,每次访问它时都没有使用 $() 或 $get 或 document.getElementById(..) 获取你关心的每个元素)然后这种类型的冲洗很有可能会让你失望。

You'd also most certainly lose any page state data you're not manually tracking/setting - textboxes with new text from the user, checkboxes newly checked by the user, etc, would reinitialize to their default state using this approach to flushing.您也肯定会丢失任何您没有手动跟踪/设置的页面状态数据 - 带有来自用户的新文本的文本框,用户新检查的复选框等,将使用这种刷新方法重新初始化为其默认状态。

Good luck - happy coding!祝你好运 - 编码愉快!

B

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

相关问题 我可以强制浏览器在javascript执行期间呈现DOM更改 - Can I force the browser to render DOM changes during javascript execution 我可以强制 chrome 或其他浏览器使用旧版本的 javascript 吗? - Can I force chrome or another browser to use an older version of javascript? 我可以强制浏览器在继续执行javascript之前渲染DOM更改吗? - Can I force the browser to render out the DOM changes before continuing javascript execution? 我可以用Javascript按钮强制浏览器忽略缓存吗? - Can I make a Javascript button force the browser to ignore cache? 如何让浏览器看到 CSS 和 Javascript 的变化? - How can I make the browser see CSS and Javascript changes? 我可以在移动浏览器中使用javascript计时器吗? - Can I use javascript timer in a mobile browser 没有浏览器我可以使用AJAX和JavaScript吗? - Can I use AJAX and JavaScript without a browser? 网站如何使用Javascript而不在浏览器中显示任何结构化HTML? - How can a site Use Javascript and NOT display any structural HTML in the browser? JavaScript:如何强制Image()不使用浏览器缓存? - JavaScript: how to force Image() not to use the browser cache? 我无法在任何浏览器中加载 javascript 分散 plot - I can't load a javascript scatter plot in any browser
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM