为什么两个代码表现不同?

时间:2019-07-05 12:01:25

标签: javascript html

以下两个代码为什么表现不同?代码的两端之间只有一个区别,第2部分具有setTimeout

// 1
var div = document.querySelector('.move');
div.classList.add('start');
div.classList.add('move-active');
requestAnimationFrame(() => {
  div.classList.remove('start');
  div.classList.add('end');
});
div.style.display = 'block';
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>test</title>
  <style>
    .move {
      position: absolute;
      width: 100px;
      height: 100px;
      background-color: red;
    }
    
    .start {
      transform: translateX(0);
    }
    
    .move-active {
      transition: transform 3s ease;
    }
    
    .end {
      transform: translateX(100px);
    }
  </style>
</head>

<body>
  <div class="move" style="display: none;"></div>
</body>

</html>
// 2
setTimeout(() => {
  var div = document.querySelector('.move');
  div.classList.add('start');
  div.classList.add('move-active');
  requestAnimationFrame(() => {
    div.classList.remove('start');
    div.classList.add('end');
  });
  div.style.display = 'block';
}, 0); 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>test</title>
  <style>
    .move {
      position: absolute;
      width: 100px;
      height: 100px;
      background-color: red;
    }
    
    .start {
      transform: translateX(0);
    }
    
    .move-active {
      transition: transform 3s ease;
    }
    
    .end {
      transform: translateX(100px);
    }
  </style>
</head>

<body>
  <div class="move" style="display: none;"></div>
</body>

</html>

  1. 在代码的第一部分,每次浏览器刷新都会产生动画效果
  2. 但是在代码的第二部分,每次浏览器刷新都会产生动画效果

为什么setTimeout对同一代码有不同的影响? setTimeout是不是将整个代码块放入事件循环线程中,然后在JS引擎线程中执行?

1 个答案:

答案 0 :(得分:0)

我尝试了您的代码,在两种情况下,大多数情况下动画都不存在。但是有时候,when the stars align上有一个Redbox从左向右移动的动画。

我认为这取决于request animation call和纯粹的运气,而不是您对setTimeout的使用。如果在绘制Redbox之后下一次重新绘制时调用了requestAnimationFrame函数的回调,则动画将在那里。否则

但是,您可以使用setTimeout函数使此行为更可靠。以下是使用您的代码的示例。

setTimeout(() => {
    var div = document.querySelector('.move');
    div.classList.add('start');
    div.classList.add('move-active');
    setTimeout(function () {
      requestAnimationFrame(() => {
        div.classList.remove('start');
        div.classList.add('end');
      });
    }, 0);
    div.style.display = 'block';
}, 0);
.move {
  position: absolute;
  width: 100px;
  height: 100px;
  background-color: red;
}
.start {
  transform: translateX(0);
}
.move-active {
  transition: transform 3s ease;
}
.end {
  transform: translateX(100px);
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>test</title>
</head>
<body>
    <div class="move" style="display: none;"></div>
</body>
</html>

setTimeoutrequestAnimationFrame函数调用委派给下一个事件循环周期。那时,requestAnimationFrame将把回调委托给下一次重绘。在大多数情况下,这应该删除start类,并在元素绘制完成后将end类添加到元素中,以使动画发生。