为什么在应用类以使我的转换生效时需要setTimeout?

我有一个应用了过渡的元素。 我想通过向元素添加一个类来控制转换,这会导致转换运行。 但是,如果我过快地应用该类,则不会发生过渡效果。

我假设这是因为.shown在同一个事件循环中放置到div上,就像将.foo放在DOM上一样。 这会诱使浏览器认为它是使用opacity: 1创建的opacity: 1因此没有实现转换。

我想知道是否有一个优雅的解决方案,而不是将我的类包装在setTimeout中。

这是一个片段:

 var foo = $('
', { 'class': 'foo' }); foo.appendTo($('body')); setTimeout(function(){ foo.addClass('shown'); });
 .foo { opacity: 0; transition: opacity 5s ease; width: 200px; height: 200px; background-color: red; } .foo.shown { opacity: 1; } 
  

实际上,重点不在于setTimeout,而在于如何呈现元素。

只有在使用属性值呈现元素时才会显示CSS过渡,然后更改此属性。 但是一旦你append了元素,它并不意味着它被渲染。 简单地添加setTimeout是不够的。 认为它可能适合您,在某些浏览器版本中它将无法正常工作! (主要是Firefox)

关键在于元素的渲染时间。 您可以通过请求视觉样式属性,然后更改类来强制DOM渲染,而不是setTimeout

 var foo = $('
', { 'class': 'foo' }); foo.appendTo($('body')); //Here I request a visual render. var x = foo[0].clientHeight; //And it works, without setTimeout foo.addClass('shown');
 .foo { opacity: 0; transition: opacity 5s ease; width: 200px; height: 200px; background-color: red; } .foo.shown { opacity: 1; } 
  

当你做javascript之后立即依赖的DOM操作时,你需要暂时暂停javascript执行以便让渲染能够赶上,因为这将是异步完成的。 所有空白的setTimeout都会将代码移动到当前执行管道的末尾。 浏览器必须完成呈现新布局才能遵循转换的触发器,因此setTimeout是一个好主意,在我看来是最优雅的解决方案。