javascript - Why do two codes perform differently?
问题描述
Why do the following two codes perform differently? There is only one difference between the two ends of the code which part 2 has a 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>
- In the first part of the code, each browser refresh will have animation effect
- But in the second part of the code, each browser refresh will have animation effect
Why does setTimeout have different effects on the same code? Isn't setTimeout putting the whole code block in the event loop thread and then executing it in the JS engine thread?
解决方案
I tried your code and in both cases, most of the time the animation was not there. But sometimes, when the stars align, there was an animation of the Redbox moving from left to right.
I think this is dependent on the request animation call and pure luck instead of your usage of setTimeout
. If the callback of requestAnimationFrame
function is called on the next repaint after the Redbox has been painted, then the animation will be there otherwise not.
You can, however, make this behavior more reliable using the setTimeout
function. Below is an example using your code.
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>
setTimeout
will delegate the requestAnimationFrame
function call to the next event loop cycle. At that time, requestAnimationFrame
will delegate the callback to the next repaint. This should, in most cases, remove the start
class and add the end
class to the element after it has been painted resulting in the animation taking place.
推荐阅读
- android - 如何将预编译的二进制文件集成到 AOSP Android 构建中?
- python - 从 NCBI 网页中提取特定的 Fasta 数据
- arrays - 我无法从对象中获取值。获取未定义的对象错误
- python - 使用 Python splitlines() 将文本文件转换为列表,同时还将一些行组合成列表中的单个项目
- php - php-express - 如何查找服务器信息
- c# - winspool.Drv ClosePrinter 实际上并没有打印,但我可以在队列中看到它 c#
- r - ggplot2中的小时刻度
- terraform - terraform 查找默认值必须与地图元素具有相同的类型
- node.js - 安装 nodemailer 导致找不到模块错误
- sql-server - 如何将此 SQL Server 公式转换为 Excel 公式?