JavaScript 函数和 UI 更新
JavaScript function and UI updates
>我有一个以下函数,可以将相对位置的元素从现在的位置滑出1000px。
for (var i = 0; i < 1000; i++) {
$('.my-element').css(
'left',
parseInt($('.my-element').css('left'), 10) + 1
);
}
这不会产生滑动效果。相反,在执行结束时,元素会突然向右移动 1000px。
现在,如果我将 UI 更新包装在 setTimeout 中,如下所示:
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和浏览器渲染概念。任何能启发我的人都会不胜感激。
注意:以上示例纯粹是为了理解目的,而不是尝试创建一个JS函数来滑动DOM元素。
这可能是最好的思考方式。浏览器可以执行以下两项操作之一。它要么运行你的javascript,要么渲染webapge,它不能同时做这两件事。
这是因为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
毫秒。它们都将移动一个div 总共 distance
像素。但是,一个(setTimeout(将具有可见的动画,而另一个将刚刚拍摄。如果您使同步方法的延迟或距离太长,您实际上会冻结浏览器,assync 解决方案不会有这个问题!
http://jsfiddle.net/j79s4o4w/3/
- 如何在范围值更改时使用 angularJs 更新 UI
- 只有当alert()在带有AJAX的internet explorer中使用时,Javascript才会更新UI
- UI网格AngularJS-如何更新UI网格中的列标题
- jQuery UI 滑块动画未更新 UI vValue
- Safari在表单提交期间未更新UI
- 在Backbone Collections中搜索,使用React更新UI
- 角度指令的父作用域未更新UI
- 正在更新UI路由器状态更改上的父作用域
- 检查有效性以更新 UI
- 当可观察数组是其他模型的属性时,挖空不会更新 UI
- 在挖空中更新视图模型并更新 UI
- 值属性的输入类型=“时间”绑定不会使用角度更新 UI
- 挖空模板绑定未更新 UI
- Knockout observableArray项属性更改没有't更新UI
- 使用setTimeout()angularjs可以缓慢更新UI
- 如何在数据发生更改时更新UI
- Aurelia验证器没有't更新UI
- 推入ko.observableArray未更新UI
- AngularJS/ng-grid - 使用拼接更新数组不会更新 UI
- Angular Modal-更新UI(对象已移动到其他日期)