DOM渲染是否在单个(同步)函数执行期间被禁止阻止?

时间:2013-11-27 19:25:24

标签: javascript dom html-rendering

DOM阻塞是很多人不熟悉JavaScript严格的单线程同步执行模型的事情,但是它通常只是我们想以某种方式解决的问题(使用超时,网络工作者等)。一切都很好。

但是,我想知道阻止实际的用户可见渲染是否可以实际依赖。在大多数浏览器中,我90%确定它是事实上的情况,但我希望这不仅仅是一个快乐的一致事故。我似乎无法从DOM规范或MDM等供应商文档中找到任何明确的陈述。

令我担心的是,虽然看到页面确实看不到对DOM的更改,但内部DOM几何(包括CSS转换和过滤器)确实在同步执行期间实际更新。例如:

console.log(element.getBoundingRect().width);
element.classList.add("scale-and-rotate");
console.log(element.getBoundingRect().width);
element.classList.remove("scale-and-rotate");

...确实会报告两个不同的宽度值,但页面不会出现到flash。在添加类(使用while循环)后同步等待也不会使临时更改可见。在Chrome中执行时间轴跟踪显示内部绘制和重新绘制正在发生相同,这是有道理的......

我担心的是,缺少一个特定的原因,一些浏览器,比如那些处理动力不足的移动CPU的浏览器,可能会选择在期间用户可见的布局中实际反映那些内部计算函数的执行,因此在这种临时操作期间会导致丑陋的“闪现”。所以,更具体地说,我要问的是:他们是否有特定的理由不这样做?

(如果你想知道为什么我会关心这一点,我有时需要使用getBoundingRect为某个状态的元素测量计算尺寸,以计划间距或动画或其他类似的东西,而不是实际放置它们在那个州或首先制作动画......)

2 个答案:

答案 0 :(得分:4)

根据各种来源,获取DOM元素的位置或大小将在必要时触发输出的重绘,以便返回的值正确。事实上,正如Alexander SkutinDaniel Norton所报告的那样,阅读元素的offsetHeight已经成为强制重画的一种方式。

Paul Irish列出了导致重绘或重排的几个操作。其中包括这些元素框度量方法和属性:

  
      
  • elem.offsetLeft,elem.offsetTop,elem.offsetWidth,elem.offsetHeight,
  •   
  • elem.offsetParent elem.clientLeft,elem.clientTop,elem.clientWidth,
  •   
  • elem.clientHeight elem.getClientRects(),elem.getBoundingClientRect()
  •   

Stoyan Stefanov描述了浏览器用于优化重新绘制的策略(例如,排队DOM更改并批量执行),并添加以下注释:

  

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

     
      
  1. offsetTop,offsetLeft,offsetWidth,offsetHeight
  2.   
  3. scrollTop / Left / Width / Height
  4.   
  5. clientTop /左/宽度/高度
  6.   
  7. getComputedStyle()或IE中的currentStyle
  8.         

    以上所有内容基本上都是请求关于的样式信息   一个节点,只要你这样做,浏览器就必须给你最大的帮助   最新的价值。为此,它需要应用所有预定的   改变,冲洗队列,咬紧牙关并进行回流。

答案 1 :(得分:2)

Javascript中没有任何与并发相关的东西,但事实并非如此。 JS根本没有定义并发模型。一切都是快乐事故或多年的共识。

也就是说,如果你的函数没有对像XMLHttpRequest或“alert”之类的奇怪事情进行任何调用,你基本上可以将它视为单线程而没有中断。