简体   繁体   English

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

[英]very simple JavaScript / jQuery example: unexpected evaluation order of instructions

I am surprised by the fact that a CSS3 transition rule applied via jQuery after a jQuery-based CSS property change actually animates this property change. 我很惊讶基于jQuery的CSS属性更改通过jQuery应用的CSS3转换规则实际上动画了此属性更改。 Please have a look at http://jsfiddle.net/zwatf/3/ : 请看http://jsfiddle.net/zwatf/3/

Initially, a div is styled by two classes and has a certain height (200px) due to the default CSS properties of these two classes. 最初,div由两个类设置样式,并且由于这两个类的默认CSS属性而具有一定的高度(200px)。 The height is then modified with jQuery via removal of one class: 然后通过删除一个类使用jQuery修改高度:

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

This reduces the height from 200px to 15px. 这将高度从200px降低到15px。

After that, a transition rule is applied to the container via addition of a class: 之后,通过添加类将转换规则应用于容器:

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

What is happening is that the reduction of the height becomes animated (on Firefox and Chrome, at least). 发生的事情是高度的降低变得生动(至少在Firefox和Chrome上)。 In my world, this should not happen if the order of instructions has any meaning. 在我的世界中,如果指令的顺序有任何意义,这不应该发生。

I guess this behavior can be very well explained. 我想这种行为可以很好地解释。 Why is that happening? 为什么会这样? How can I prevent it? 我该怎样预防呢?

This is what I want to achieve: 这就是我想要实现的目标:

  1. modify default style with jQuery (not animated by CSS3 transition!) 用jQuery修改默认样式(不是通过CSS3过渡动画!)
  2. apply transition rule with jQuery 使用jQuery应用转换规则
  3. change a property with jQuery (animated by CSS3 transition) 使用jQuery更改属性(通过CSS3过渡动画)

(1) and (2) should happen as quickly as possible, so I do not like working with arbitrary delays. (1)和(2)应该尽快发生,所以我不喜欢任意延迟。

When running a script, the browser will usually defer DOM changes to the end to prevent unnecessary drawing. 运行脚本时,浏览器通常会将DOM更改推迟到最后,以防止不必要的绘制。 You can force a reflow by reading/writing certain properties: 您可以通过读/写某些属性来强制重排:

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

jsFiddle 的jsfiddle

Or you can use setTimeout with a short duration, which does basically the same thing by letting the browser reflow automatically, then adding the class. 或者你可以使用短时间的setTimeout ,这通过让浏览器自动重排,然后添加类来完成同样的事情。

Why is that happening? 为什么会这样?

I guess because the DOM sees them applied together; 我猜是因为DOM看到它们一起应用; immediate consecutive actions are usually cached instead of being applied one after the other. 立即连续的动作通常被缓存而不是一个接一个地应用。

How can I prevent it? 我该怎样预防呢?

A (very small) timeout should do it: http://jsfiddle.net/zwatf/4/ 一个(非常小的)超时应该这样做: http//jsfiddle.net/zwatf/4/

(from the comments) Manually triggering a reflow also helps: http://jsfiddle.net/zwatf/9/ (来自评论)手动触发回流也有助于: http//jsfiddle.net/zwatf/9/

I do not like working with arbitrary delays. 我不喜欢任意拖延。

Then I think the only other possible way is to remove the height from the animated css properties, ie you need to explicitly state which ones you wanted to animate: http://jsfiddle.net/zwatf/5/ 然后我认为唯一可能的方法是从动画css属性中删除height ,即你需要明确说明你想要动画的那些: http//jsfiddle.net/zwatf/5/

i think, it just happens too fast. 我认为,它发生得太快了。 if you do this: 如果你这样做:

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

it will behave as you expected, right? 它会像你期望的那样表现,对吧?

ok, fine, i tested it, but I didn't realize it didn't work as expected. 好的,很好,我测试了它,但我没有意识到它没有按预期工作。 Here an alternative to make it up: 这是一个替代方案:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM