![](/img/trans.png)
[英]Can I force the browser to render DOM changes during javascript execution
[英]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
以上所有这些本质上都是请求有关节点的样式信息,并且无论何时执行此操作,浏览器都必须为您提供最新的值。 为此,它需要应用所有计划的更改,刷新队列,咬紧牙关并进行回流。
(这个答案曾经链接到一个现在 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.