AngularJS指令在元素完全加载之前运行

Rob*_*ier 11 angularjs angularjs-directive

我有一个指令附加到<table>模板内的动态生成的元素.该指令在link函数内操作该表的DOM .问题是指令在表呈现之前运行(通过评估ng-repeat指令) - 表是空的.

如何在表完全呈现后确保指令运行?

<table directive-name>
    <tr ng-repeat="...">
        <td ng-repeat="..."></td>
    </tr>
</table>


module.directive("directiveName", function() {
    return {
        scope: "A",
        link: function(scope, element, attributes) {
            /* I need to be sure that the table is already fully
               rendered when this code runs */
        }
    };
});
Run Code Online (Sandbox Code Playgroud)

New*_*Dev 6

一般来说,只要对<table>元素有一个指令,就不能"完全确定" .

但在某些情况下你可以肯定.在您的情况下,如果内部内容是ng-repeat-ed,那么如果ngRepeat已经准备好的项目数组,那么实际DOM元素将在摘要周期结束时准备就绪.您可以在$timeout0延迟后捕获它:

link: function(scope, element){
  $timeout(function(){
    console.log(element.find("tr").length); // will be > 0
  })
}
Run Code Online (Sandbox Code Playgroud)

但是,从一般意义上讲,您无法确定捕获内容.如果ngRepeated数组还没有呢?或者如果有的话ng-include呢?

<table directive-name ng-include="'templates/tr.html'">
</table>
Run Code Online (Sandbox Code Playgroud)

或者,如果有一个自定义指令的工作方式不同ngRepeat,该怎么办?

但是如果你完全控制了内容,一种可能的方法就是将一些辅助指令作为最里面/最后一个元素包含在内,并directiveName在链接时让它与父节点联系:

<table directive-name>
    <tr ng-repeat="...">
        <td ng-repeat="...">
          <directive-name-helper ng-if="$last">
        </td>
    </tr>
</table>
Run Code Online (Sandbox Code Playgroud)
.directive("directiveNameHelper", function(){
  return {
    require: "?^directiveName",
    link: function(scope, element, attrs, ctrl){
      if (!ctrl) return;

      ctrl.notifyDone();
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

  • 我认为这是最全面的答案.谢谢.我仍然不明白为什么`$ timeout`有0延迟保证DOM准备就绪,但我想我会在Angular的'$ timeout`文件中找到它. (2认同)
  • @Robert,`ng-repeat`有一个`$ scope.$ watchCollection` - 这在链接阶段之后触发,如果数组准备就绪,那么它会转换`ng-repeat`-ed模板并将它放在DOM中.在此之后立即执行带有0延迟的`$ timeout` (2认同)

bos*_*sch 5

尝试包装$timeout链接函数中的代码,因为它将在呈现DOM之后执行。

$timeout(function () {
    //do your stuff here as the DOM has finished rendering already
});
Run Code Online (Sandbox Code Playgroud)

不要忘记$timeout在指令中添加:

.directive("directiveName", function($timeout) {
Run Code Online (Sandbox Code Playgroud)

有很多选择,但是我认为这是更清洁的方法,因为$ timeout在渲染引擎完成工作后执行。