答案
$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 在主线程上添加了 angular 模板。从第一次 $document.ready() 到最后一次 $timeout 执行的总时间接近 500 毫秒。
在一种特殊情况下,设置了组件的值,然后在 $timeout 中稍后更改 text() 值,必须增加 $timeout 值直到它起作用(即使可以在 $timeout 期间找到该元素)。3rd 方组件中的一些异步导致值优先于文本,直到经过足够的时间。另一种可能性是 $scope.$evalAsync,但没有尝试过。
我仍在寻找一个事件,它告诉我 DOM 已经完全稳定下来并且可以被操纵以便所有情况都能正常工作。到目前为止,需要一个任意的超时值,这意味着充其量这是一个可能无法在慢速浏览器上工作的杂物。我还没有尝试过像 liveQuery 和发布/订阅这样的 JQuery 选项,它们可能有效,但肯定不是纯角度的。