JavaScript功能和UI更新
我有一个以下功能,将相对定位的元素从现在的位置滑出1000px。
for (var i = 0; i < 1000; i++) {
$('.my-element').css(
'left',
parseInt($('.my-element').css('left'), 10) + 1
);
}
这不会产生滑动效果。 相反,在执行结束时,元素突然向右移动1000px。
现在,如果我在下面的setTimeout中包装UI更新:
for (var i = 0; i < 1000; i++) {
setTimeout(function () {
$('.my-element').css(
'left',
parseInt($('.my-element').css('left'), 10) + 1
);
}, 0);
}
这产生了元素向右滑动1000px的视觉效果。
现在,根据我的解释和这个SO线程,为什么setTimeout(fn,0)有时候有用?,UI更新在浏览器事件队列中排队,就像同步回调排队等待setTimeout回调一样。
因此,在第一种情况下,基本上,执行for循环时将执行1000个UI更新队列。
在第二种情况下,首先创建一个包含1000个setTimeout回调的队列,并在执行时创建1000个UI更新的另一个队列。
因此,最终,这两种情况都会创建1000个UI更新的相同队列。 那么为什么视觉效果的差异呢?
我必须在这里查看一些重要的JavaScipt和浏览器渲染概念。 任何能够启发我的人都会非常感激。
注意:以上示例纯粹是为了理解目的,而不是尝试创建用于滑动DOM元素的JS函数。
这可能是考虑它的最佳方式。 浏览器可以做两件事之一。 要么它运行你的JavaScript或它呈现网页,它不能做到这一点。
这是因为JavaScript代码是100%阻止的,这意味着在浏览器执行所有阻止代码之前,它绝对不会放弃控制权。
你的第一个例子只包含了阻止代码,所以浏览器从来没有机会渲染,直到元素已经到达需要的位置。
你的第二个例子包含了使用setTimeout(延迟阻塞代码)的阻塞代码,它在浏览器的判断之间(在其延期和JavaScript运行周期之间)排队一批阻塞代码以便稍后执行(在所有其他阻塞代码完成之后)。
所以第二个例子循环将完全执行,排队1000个函数在某个时间点执行,但尽可能接近0ms。 现在阻止代码已经完成了一个或多个setTimeout可能执行或者浏览器可以渲染,但它实际上发生了什么。 但它会在呈现和执行javascript之间来回编织。
以此代码为例。
setTimeout(function () { //this makes it so the page loads and sits for a second
var delay = 100, //delay between animations
distance = 25, //total distance moved
sync = false; //should this use blocking code
if (sync) {
var i = 0,
elapsed = 0,
last = new Date();
while (i < distance) {
var now = new Date();
elapsed += (now - last);
last = now;
if (elapsed >= delay) {
move(i++);
elapsed -= delay;
}
}
} else {
for (var i = 0; i < distance; i++) {
assyncMove(i, delay * i);
}
}
function assyncMove(position, delay) {
setTimeout(function () {
move(position);
}, delay);
}
function move(position) {
$("div").css("left", position);
}
}, 1000);
您可以更改delay
, distance
和sync
变量。 两个循环等待在每个动画之间移动元素delay
毫秒。 它们都会移动一个distance
像素的总和。 然而,一个(setTimeout)将有一个可见的动画,而另一个只会拍摄。 如果您为同步方法延迟或延长距离,实际上会冻结浏览器,那么assync解决方案就不会有这个问题!
http://jsfiddle.net/j79s4o4w/3/
链接地址: http://www.djcxy.com/p/74991.html上一篇: JavaScript function and UI updates
下一篇: Why JavaScript declared variable is in the global object before initialization?