问题引入
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<style>
div{
height:300px;
transition:all 0.4s;
background:red;
width:500px;
}
</style>
<div id="div">test</div>
<input id="btn" type="button" value="click here">
<script>
btn.onclick=function(){
div.style.height="900px";//我的疑惑是为什么不先到900然后在到100px;应该如何完善?
div.style.height="100px";
}
</script>
</body>
</html>
问题出在哪里?
浏览器有一个GUI渲染线程,当需要重绘页面时渲染页面。但问题是GUI渲染线程与JS引擎是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
所以在脚本中执行对界面进行更新操作,如添加结点,删除结点或改变结点的外观等更新并不会立即体现出来,这些操作将保存在一个队列中,待JavaScript引擎空闲时才有机会渲染出来.
解决办法
解决办法是用setTimeout或者requestAnimationFrame
问:
setTimeout(function((){/xxx/},0)的实质是将某段代码放到js主线程的最后执行。实际上中途它也会被放到一个队列中,那么这个队列和之前你所说的对界面进行更新操作,如添加结点,删除结点或改变结点,将保存在一个队列中GUI渲染线程的队列是两个队列吗?
答:
经过实践,setTimeout(function(){},0)的这种方式不生效。只能把延迟时间调大一些。但是有个问题这个延迟时间会不会因不同的电脑、不同浏览器性能问题而导致过短呢。比如一个电脑内存非常小,主频很低,即使setTimeout 延迟100ms执行,但是GUI线程仍然处于挂起状态,之前的渲染队列并未执行,导致看不到效果。