我有一个使用Javascript构建UI的库,由于涉及动态内容,我有时希望将内容放到浏览器中,检查布局如何更改以支持这一点,然后根据结果执行不同的逻辑。例如:检测某些文本是否溢出并使用省略号截断它。
通常我通过发布更改来实现它,然后使用window.setTimeout(0)等待布局更新并调用其余的逻辑。这显然是次优的,因为不同的浏览器可能实现的最小超时太慢而不能防止使用大量CPU的闪烁或更快。
理想情况下,我想进行DOM更改,然后强制布局同步更新并立即内联运行“修复”逻辑。有什么想法吗?
答案 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;
上述代码将强制浏览器在渲染队列中执行更改,以便返回正确的值。
简单!!