javascript - 异步调用后 DOM 更新

标签 javascript html angularjs dom

我正在从我的服务器获取一些数据并通过 Angular 双向绑定(bind)更新 DOM。然而,它没有按预期工作,我需要将它包装在一个丑陋的 setTimeout 函数中,以便 DOM 有时间更新。

$http.post('myBackend.php', someData)
.then(function(res){
    $scope.data = res.data;
    doStuffWithDOMElements(); // Does not work
});

虽然这有效:

 $http.post('myBackend.php', someData)
 .then(function(res){
     $scope.someDataToPopulateDOMwith = res.data;
     setTimeout(function(){ doStuffWithDOMElements();}, 50); // Yup, works
 });

在没有超时的情况下给出错误的行 “无法正确读取 null” 是这样的:

let y_0 = document.getElementById("l_0").offsetTop;

在我的 index.html 中

<div id="l_{{$index}}" ng-repeat = "x in data"></div>

这很奇怪。不应该自动更新包含在 Angular“事件”中的每个 DOM 元素吗? $scope.$apply() 不起作用,也没有必要。这里有什么问题吗?

最佳答案

需要$timeout在 angularjs 中每隔一段时间就会出现一次。很可能是为了初始化一个 jQuery 插件

您的错误行:

 let y_0 = document.getElementById("l_0").offsetTop; 

是因为您的 DOM 尚未设置,您正在尝试获取尚未设置的元素,或者更确切地说是在 DOM< 中呈现/strong>.

当你使用 $timeout 时,它应该在 DOM 被 Angular 操作之后运行,并且在浏览器渲染之后运行(这在某些情况下可能会导致闪烁)。这就是为什么它在您设置 $timeout 时的情况。

如果您想了解有关摘要循环的更多信息。你应该知道 $evalAsync以及。

  • 如果代码使用来自指令的$evalAsync 进行排队,它应该在 Angular 操作 DOM 之后,但在浏览器呈现之前运行
  • 如果代码使用来自 Controller 的 $evalAsync 进行排队,它应该在 Angular 操作 DOM 之前(以及浏览器呈现之前)运行——您很少希望这样
  • 如果代码使用 $timeout 排队,它应该在 DOM 被 Angular 操作之后以及浏览器呈现之后运行(这在某些情况下可能会导致闪烁)。

此外,Angularjs 是一个javascript 框架。浏览器几乎必须同时做很多事情,其中​​之一就是执行 JavaScript。但是 JavaScript 最常用于的事情之一是要求浏览器构建一个显示元素。这通常被认为是同步完成的(特别是因为 JavaScript 不是并行执行的),但不能保证是这种情况,而且 JavaScript 没有明确定义的等待机制。

解决方案是“暂停” JavaScript 执行,让渲染线程 catch 进度。这就是超时为 0setTimeout() 的效果。它就像 C 语言中的线程/进程 yield。虽然它似乎在说“立即运行”,但它实际上让浏览器有机会完成一些非 JavaScript 的事情,这些事情在处理这段新的 JavaScript 之前一直在等待完成.

(实际上,setTimeout() 将新的 JavaScript 重新排入执行队列的末尾。请参阅评论以获得更长解释的链接。)

IE6 恰好更容易出现此错误,但我已经看到它发生在旧版本的 Mozilla 和 Firefox 中。

此外,关于为什么使用 $timeout 有时会派上用场,已经有很多文章和解释。

您可以在其中找到很好解释的链接:

关于javascript - 异步调用后 DOM 更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35744028/

相关文章:

javascript - 从指令中删除元素时,AngularJs 会自动销毁范围吗?

javascript - 禁用基于单选按钮的下拉列表

javascript - 在 ajax 调用中传递 Controller 中方法的 url

javascript - 修复了表中的左列

php - 如何使用php隐藏一个div标签

css - Shadow Dom::content css 选择器优先级?

data-binding - 使用 ng-grid 进行双向数据绑定(bind)?

javascript - 用于检索 postgres 数据的 AJAX 函数不起作用

html - 带图像的选项卡式导航

javascript - AngularJs Controller 添加模板中的所有 html 元素