答案
$scope.$watch('$viewContentLoaded',
function() {
$timeout(function() {
//do something
},0);
});
是我测试过的大多数场景中唯一适用的。在一个包含 4 个组件的示例页面中,所有这些组件都从模板构建 HTML,事件的顺序是
$document ready
$onInit
$postLink
(and these 3 were repeated 3 more times in the same order for the other 3 components)
$viewContentLoaded (repeated 3 more times)
$timeout execution (repeated 3 more times)
所以 $document.ready() 在大多数情况下是没有用的,因为 Angular 构建的 DOM 可能还远远没有准备好。
但更有趣的是,即使在 $viewContentLoaded 被触发后,仍然无法找到感兴趣的元素。
只有在 $timeout 执行后才被发现。请注意,尽管 $timeout 的值为 0,但在它执行之前已经过去了将近 200 毫秒,这表明该线程被推迟了相当长的一段时间,大概是当 DOM 在主线程上添加了角度模板时。从第一次 $document.ready() 到最后一次 $timeout 执行的总时间接近 500 毫秒。
在一个特殊情况下,设置了组件的值,然后在 $timeout 稍后更改了 text() 值,必须增加 $timeout 值直到它起作用(即使在 $timeout 期间可以找到该元素)。第 3 方组件中的某些异步导致值优先于文本,直到经过足够的时间。另一种可能性是 $scope.$evalAsync,但没有尝试过。
我仍在寻找一个事件,它告诉我 DOM 已经完全稳定下来并且可以进行操作,以便所有情况都有效。到目前为止,一个任意的超时值是必要的,这意味着充其量这是一个可能无法在慢速浏览器上工作的杂物。我没有尝试过诸如 liveQuery 和发布/订阅之类的 JQuery 选项,它们可能会起作用,但肯定不是纯角度的。