CSS转换和transitionend事件的竞争条件 - 无法找到解决方案

时间:2014-12-03 15:46:24

标签: javascript css events asynchronous transitions

我想大多数人都知道,在向DOM添加元素而不询问计算样式之后,就无法触发转换。好的,我明白了,这个问题在某种程度上是相关的。

我只需要依靠JS' transitionend'事件在转换结束后从DOM中删除元素(淡出效果)。 问题是添加一个CSS类并删除它(没有定时器)并不会触发转换,所以事件永远不会被触发,让元素永远留在DOM中。

我甚至尝试使用setTimeout(f,0)和requestAnimationFrame(f)在添加后删除类,让转换开始,但根本没有运气。 在添加/删除类之前和之后,我甚至组合调用getComputedStyle来触发重绘。仍然没有运气。

例如:http://jsfiddle.net/demian85/oprn9jzk/1/

var button = document.querySelector('button');

button.addEventListener('transitionend', function(e) { // this never gets called
    console.log(e);
    button.parentNode.removeChild(button);
});

button.classList.add('hover');
button.clientWidth;
button.classList.remove('hover');

我找到的唯一丑陋的解决方案是使用至少50毫秒延迟的setTimeout。但是我们使用的测试框架应该在与DOM交互之前等待50ms,而这根本不是一个可行的解决方案。

有谁知道我该如何处理这种情况?为什么没有任何transitionstart事件?

pd:在Chrome 39中测试

感谢。

1 个答案:

答案 0 :(得分:0)

好的,我想我现在理解你的要求了:你在你的示例代码中使用了悬停类,但我实际上假设你想使用:hover伪类来触发淡入淡出过渡。但是你担心如果用户很快离开(<50ms),就不会发送transitionend事件。

答案是不使用:悬停。相反,添加鼠标悬停侦听器并手动添加导致淡入淡出过渡的类,并且不要将其删除。这样,淡入淡出转换可以保证完成,并且转发事件肯定会被触发。

E.g。 http://jsfiddle.net/vw3t627g/1/

var button = document.querySelector('button');

button.addEventListener('mouseover', function() {
   button.classList.add('bye-bye'); 
});

button.addEventListener('transitionend', function(e) {
    console.log(e);
    button.parentNode.removeChild(button);
});