在$ digest之后推迟angularjs监视执行(提升DOM事件)

ano*_*ous 31 angularjs angularjs-directive

我有一个触发DOM事件的手表:

scope.$watch(function() { return controller.selected; }, function(selected) {
    if (selected) {
        $input.trigger('focus');
    }
});
Run Code Online (Sandbox Code Playgroud)

问题是我在'焦点'上有一个处理程序scope.$apply.

$input.bind('focus', function() {
    scope.$apply(function() { controller.focused = true; });
});
Run Code Online (Sandbox Code Playgroud)

因此当我$watch从内部触发$digest它时会导致错误,因为它试图触发另一个错误$digest.

我的解决方法是将触发器放入$timeout.

scope.$watch(function() { return controller.selected; }, function(selected) {
    if (selected) {
        $timeout(function() { $input.trigger('focus'); });
    }
});
Run Code Online (Sandbox Code Playgroud)

这工作......到目前为止.这是处理这个问题的正确方法吗?我不确定这是否能抓住每一个案例,并且想知道是否有一个有角度的批准方式让一段代码推迟到摘要之后.

谢谢!

Mar*_*cok 65

$ timeout通常是在摘要周期之后(以及浏览器呈现之后)运行的东西.

$timeout将导致在执行该函数后执行另一个摘要循环.如果您trigger不影响任何Angular,可以将invokeApply参数设置false为避免运行另一个摘要周期.

如果您希望在浏览器呈现之前运行回调:如果代码使用$evalAsync 指令排队,则它应该在Angular操纵DOM之后但在浏览器呈现之前运行.但是,如果代码使用$evalAsync 控制器进行排队,则它将在Angular操纵DOM之前运行(在浏览器呈现之前).另请参见/sf/answers/1211263161/.

  • @FelikZ,如果代码使用来自_directive_的$ evalAsync排队,它应该运行_after_ DOM已被Angular操纵,但_before_浏览器呈现.但是,如果代码使用来自_controller_的$ evalAsync排队,它将运行_before_ DOM已被Angular操纵(并且_before_浏览器呈现).另见http://stackoverflow.com/a/17303759/215945 (2认同)