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

时间:2014-09-17 21:16:54

标签: javascript jquery html css css3

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

我假设这是因为.shown在同一事件循环期间被置于div上,而.foo被置于DOM上。这会诱使浏览器认为它是使用opacity: 1创建的,因此不会实现转换。

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

这是一个片段:

var foo = $('<div>', {
    '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;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

2 个答案:

答案 0 :(得分:9)

实际上,关键不在于setTimeout,而在于如何渲染元素。

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

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

&#13;
&#13;
var foo = $('<div>', {
    'class': 'foo'
});

foo.appendTo($('body'));

//Here I request a visual render.
var x = foo[0].clientHeight;

//And it works, without setTimeout
foo.addClass('shown');
&#13;
.foo {
    opacity: 0;
    transition: opacity 5s ease;
    width: 200px;
    height: 200px;
    background-color: red;
}

.foo.shown {
    opacity: 1;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

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