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

非常简单的JavaScript/jQuery示例:指令的意外求值顺序,javascript,jquery,css,css-transitions,Javascript,Jquery,Css,Css Transitions,我感到惊讶的是,在基于jQuery的CSS属性更改之后,通过jQuery应用的CSS3转换规则实际上为该属性更改设置了动画。请看一看: 最初,一个div由两个类设置样式,并且由于这两个类的默认CSS属性而具有一定的高度(200px)。然后通过删除一个类,使用jQuery修改高度: $('.container').removeClass('active'); 这将高度从200px降低到15px 之后,通过添加类将转换规则应用于容器: $('.container').addClass('all-t

我感到惊讶的是,在基于jQuery的CSS属性更改之后,通过jQuery应用的CSS3转换规则实际上为该属性更改设置了动画。请看一看:

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

$('.container').removeClass('active');
这将高度从200px降低到15px

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

$('.container').addClass('all-transition');
现在的情况是,高度的降低变成了动画(至少在Firefox和Chrome上)。在我的世界里,如果指令的顺序有任何意义,这就不应该发生

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

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

  • 使用jQuery修改默认样式(不通过CSS3转换设置动画!)
  • 使用jQuery应用转换规则
  • 使用jQuery更改属性(通过CSS3转换设置动画)

  • (1) (2)应该尽可能快地发生,所以我不喜欢在任意延迟的情况下工作。

    我认为,这种情况发生得太快了。如果您这样做:

    $('.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
    });
    
    为什么会这样


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

    我怎样才能预防它

    (非常小的)超时应该可以:

    (来自评论)手动触发回流也有助于:

    我不喜欢随意拖延工作


    然后,我认为唯一其他可能的方法是从动画css属性中删除
    高度,也就是说,您需要明确说明您要设置哪些属性的动画:

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

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


    或者您可以使用持续时间较短的
    setTimeout
    ,这与让浏览器自动回流,然后添加类基本相同。

    No.没有回调参数Bergi是正确的。您没有尝试代码,也没有查找文档。我认为这并不是因为事情发生得“太快”。事情发生得不受控制。来自其他语言,我本以为当
    removeClass
    返回操作已经执行时。显然,我们正在处理异步执行。在这种情况下,有一个回调参数就好了。我还没有尝试基于
    promise
    的方法,但从相应的文档来看,这似乎也是一种相当合理的方法——如果“一旦绑定到集合的特定类型的所有操作(无论是否排队)都结束”对于我们需要等待的CSS更改也是如此。这真的很奇怪,可能是一个浏览器错误。我更新了fiddle以使用removeClass,并在第一个函数之前设置了一个调试器中断。如果您跳过第一个函数,然后从那里运行JS,那么一切都会按照您的预期工作。如果没有debugger语句,就会出现与您看到的相同的奇怪动画效果。removeClass中没有使用任何动画的代码。顺便说一句,我在Chrome上看到了这一点。mac上的Chrome 25.0.1364.152显示的动画不正确。mac上的Safari 5.1.7(6534.57.2)-动画显示不正确。@abbood:我看到的是Firefox 20和Chrome 25的动画@@abbood类似地,你能说你在哪个浏览器中没有看到任何动画吗?Opera只在类未应用于DOMready时显示,但有一个超时:Bergi,您知道jQuery是否负责这种“缓存”行为,或者这是浏览器本身吗?“我猜是因为DOM看到它们一起应用了”,这应该被称为“这是一个浏览器错误”。DOM是为了遵循它所给出的规则,而不仅仅是按照感觉来实现它们。感谢Bergi提出的相关问题。与超时不同,根据以下规则强制回流似乎是安全的“当使用offsetWidth等属性或getComputedStyle等方法进行测量时,会产生这种效果。即使不使用这些数字,在浏览器仍在缓存更改时简单地使用其中任何一个都足以触发隐藏的回流。“@Danack:我认为这是快速浏览器的一项功能,但您可以免费为gecko/webkit引擎提交一些错误报告:-)如果您这样做,请链接它们here@Bergi是的,“这是一个功能,不是一个bug“CSS实际上并没有描述如何以及何时解决样式,大多数浏览器都会批量更改样式。”这对我来说似乎很疯狂,但嘿,我是谁,希望API的行为可以预测,而不仅仅是它们的感觉呢?-)是的,谢谢,@Bergi提到的相关问题也让我想到了这项技术。我会做一些测试。到目前为止,这种“强制回流法”在我看来是相当可靠的。是的,它在极光和金丝雀中对我都有效。IE10一开始似乎没有bug,但添加行不会导致问题。它是有效的,你看——Bergi比你更早地向我指出了这一点,所以你们都赢得了绿色复选标记。我不知道该怎么办;)这才是真正的问题,你们两个都赢得了。我现在把它交给了丹尼斯,因为我认为最可靠的方法是他的答案的核心。W.r.t.你的回答,这只是评论的一部分。