要清楚地了解情况,您需要了解CSSOM和DOM之间的关系。
在先前的Q / A中,我对 重绘 过程的工作方式进行了一些开发。 基本上,有三个步骤,DOM操作,重排和绘制。
- 第一个( DOM操作 )只是修改js对象,并且都是同步的。
第二个( reflow ,又称 layout )是我们感兴趣的一个,并且稍微复杂一些,因为只有某些DOM方法和绘画操作需要它。它包括更新所有CSS规则并重新计算页面上每个元素的所有计算样式。
作为一项相当复杂的操作,浏览器将尝试尽可能少地执行此操作。第三次( 绘画 )最多每秒最多只能完成60次(仅在需要时)。
CSS过渡通过从一种状态过渡到另一种状态来工作。为此,他们查看元素的 最后一个计算值 以创建初始状态。
由于浏览器仅在需要时才重新计算所计算的样式,因此在过渡开始时,您应用的所有DOM操作均无效。
因此,在您的第一种情况下,当计算过渡的初始状态时,
.b { computedStyle: {display: none} }…就是这样。
因为,是的,这
display: none就是CSSOM的强大功能。如果元素具有
display: none,则不需要绘制它,则它不存在。
因此,我什至不确定转换算法是否会启动,但是即使这样,初始状态对于 任何可 转换值也将是无效的,因为所有计算出的值都为null。
.a从一开始就可见您的元素没有此问题,可以进行过渡。
如果你能使其与延迟(诱导工作
$.animate),这是因为DOM MANIP“这确实改变之间的
display财产,这种延迟DOM
MANIP的执行”,做触发转换,浏览器确实触发一个 回流 (例如,因为屏幕之间出现了 垂直 同步,并且启动了 绘画 操作)。
现在,这不是问题的一部分,但是由于我们确实了解发生了什么,因此我们也 可以更好地控制它 。
实际上,某些DOM方法确实需要具有最新的计算值。举例来说
Element.getBoundingClientRect,或
element.offsetHeight或
getComputedStyle(element).height等等。所有这些需要
整个页面 已经更新,以便拳击正确做出的计算值(例如一个元素可以有一个保证金推或多或少等)。
这意味着我们不必在的时候,浏览器将触发这个未知的 回流 ,我们可以迫使它这样做时,我们想要的。
但是请记住, 页面上的所有元素都 需要更新,这不是一个小操作,如果浏览器宽容地这样做,这是有充分理由的。
因此,最好偶尔使用它,每帧最多使用一次。
幸运的是,WebAPI使我们能够在绘画操作发生之前钩住一些js代码:requestAnimationframe。
因此,最好的方法是在此预绘画回调中仅强制执行一次重排,并从该回调中调用需要更新值的所有内容。
$('button').on('click',function(){ $('.b').show(); // apply display:block synchronously requestAnimationframe(() => { // wait just before the next paint document.body.offsetHeight; // force a reflow // trigger the transitions $('.b').css('right','80%'); $('.a').css('right','80%'); });})body { width:800px; height:800px;}div { width:50px; height:50px; background-color:#333; position:absolute; display:none; right:5%; top:0; transition:right .5s cubic-bezier(0.645, 0.045, 0.355, 1); color: white;}.a { display:block; top:60px;}<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><div >A</div><div >B</div><button>Launch</button>但老实说,设置起来并不总是那么容易,因此,如果您确定某些东西会偶尔被触发,那么您可能会很懒惰并同步执行所有操作:
$('button').on('click',function(){ $('.b').show(); // apply display:block document.body.offsetHeight; // force a reflow // trigger the transitions $('.b').css('right','80%'); $('.a').css('right','80%');})body { width:800px; height:800px;}div { width:50px; height:50px; background-color:#333; position:absolute; display:none; right:5%; top:0; transition:right .5s cubic-bezier(0.645, 0.045, 0.355, 1); color: white;}.a { display:block; top:60px;}<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><div >A</div><div >B</div><button>Launch</button>


