jQuery 排队 css 方法

jQuery queuing css methods

我发现了一些行为,据我所知,jQuery.css() 的工作原理似乎很奇怪。我知道,它不可排队,但在下面的 fiddle 中,当我连续应用 2 个 css 方法时 - 但不是在一个队列中,它的行为不同,通过 setTimeout 延迟 1 毫秒应用它们。

结果是,一个框淡入,但另一个框立即变为不透明度 1。

有人可以澄清一下吗。

var fadingBox = $("<div></div>")
  .css({
    "opacity": "0"
  })
  .appendTo("#cont");


setTimeout(function() {
  fadingBox.css({
    "background": "red",
    "opacity": "1"
  });
}, 1);


var notFadingBox = $("<div></div>")
  .css({
    "background": "red",
    "opacity": "0"
  })
  .appendTo("#cont");


notFadingBox.css("opacity", "1");
div {
  -webkit-transition: opacity 2s;
  -moz-transition: opacity 2s;
  -ms-transition: opacity 2s;
  -o-transition: opacity 2s;
  transition: opacity 2s;
  height: 50px;
  width: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="cont">

</div>

https://jsfiddle.net/Lukis/0mbz7e9x/35/

编辑:更新了之前错误的 jsFiddle。

浏览器的布局引擎无法区分元素的开始状态和结束状态,因为在它看来,开始状态 (opacity: 0) 和结束状态 (opacity: 1) 都已设置同时

为了让布局引擎理解应该有分隔,您需要在开始和结束之间造成中断。不幸的是,据我所知,没有合法的或 "nice" 方法可以做到这一点,因此您需要使用变通方法。

setTimeout 是强制分离的一种方法,这就是您的第一个示例起作用的原因。

(这种方法经常被误解,所以我觉得有必要澄清一下,这不起作用,因为你是 "giving the browser time",而是因为 setTimeout 创建了一个队列回调。然后单独执行此回调,绕过同时设置两个状态的初始问题。)

请参阅下面的示例,我将超时设置为 0 并且仍然获得正确的转换:

var $fadingBox= $("<div></div>")
    .css({"background" : "red","opacity": "0"})
    .appendTo("#cont");

setTimeout(function(){
    $fadingBox.css("opacity", "1");
}, 0);
#cont div {
  transition: 2s opacity;
  padding: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="cont"></div>

一些功能也会导致布局引擎 interruption/refresh,尽管我不会总是依赖这些工作,因为您正在利用可能在未来优化中删除的内容。

例如,您可以利用元素的 offsetHeight 属性,其 getter 功能使布局引擎 "pause":

var $fadingBox = $("div");
$fadingBox.css("opacity", "0");
$fadingBox[0].offsetHeight;      //LAYOUT ENGINE REFRESH
$fadingBox.css("opacity", "1");
div {
  background: red;
  transition: 2s opacity;
  padding: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>