非常简单的JavaScript / jQuery示例:意外的评估指令顺序

时间:2013-03-03 13:39:55

标签: javascript jquery css3 css-transitions

我感到惊讶的是,在基于jQuery的CSS属性更改后,通过jQuery 应用的CSS3转换规则实际上为此属性更改设置了动画。请查看http://jsfiddle.net/zwatf/3/

最初,div由两个类设置样式,并且由于这两个类的默认CSS属性而具有一定的高度(200px)。然后通过删除一个类来使用jQuery修改高度:

$('.container').removeClass('active');

这会将高度从200px降低到15px。

之后,通过添加类来将转换规则应用于容器:

$('.container').addClass('all-transition');

正在发生的事情是高度的降低变得生动(至少在Firefox和Chrome上)。在我的世界中,如果指令的顺序有任何意义,就不会发生这种情况。

我想这个行为可以很好地解释。为什么会这样?我该如何预防呢?

这就是我想要实现的目标:

  1. 使用jQuery修改默认样式(不是通过CSS3过渡动画!)
  2. 使用jQuery应用转换规则
  3. 使用jQuery更改属性(通过CSS3过渡动画)
  4. (1)和(2)应该尽快发生,所以我不喜欢任意延迟。

3 个答案:

答案 0 :(得分:4)

运行脚本时,浏览器通常会将DOM更改推迟到最后,以防止不必要的绘制。您可以通过读/写某些属性来强制重排:

var container = $('.container').removeClass('active');
var foo = container[0].offsetWidth;  //offsetWidth makes the browser recalculate
container.addClass('all-transition');

jsFiddle

或者您可以使用短暂的setTimeout,这通过让浏览器自动重排,然后添加类来实现基本相同的事情。

答案 1 :(得分:3)

  

为什么会这样?

我猜是因为DOM看到它们一起应用;立即连续的动作通常被缓存而不是一个接一个地应用。

  

我该如何预防?

(非常小的)超时应该执行:http://jsfiddle.net/zwatf/4/

(来自评论)手动触发重排也有助于:http://jsfiddle.net/zwatf/9/

  

我不喜欢处理任意延迟。

然后我认为唯一可能的另一种方法是从动画css属性中删除height,即你需要明确说明你想要制作哪些动画:http://jsfiddle.net/zwatf/5/

答案 2 :(得分:1)

我想,它发生得太快了。如果你这样做:

$('.container').toggleClass('active',function() {
    $('.container').addClass('all-transition');
});

它会按照您的预期行事,对吧?

好的,很好,我测试了它,但我没有意识到它没有按预期工作。 这是一个替代方案:

$('.container').removeClass('active').promise().done(function(){
    $('.container').addClass('all-transition');

    $('.container').css('height','300'); //to see the easing
});