简单地说,我的情况是我从运行阶段触发一个事件。在几个指令中,我监听此事件并执行代码。问题是在我的开发机器上,一些指令在编译指令之前通过 templateUrl 属性获取模板。因此它将错过该事件。可以使用 $locationChangeSuccess 事件重现此行为。
var myApp = angular.module('myApp', []);
myApp.directive('directiveOne', function(){
return {
templateUrl: '/some/url.html',
controller: function($rootScope){
$rootScope.$on('$locationChangeSuccess', function(){
console.log('Directive one callback');
});
}
}
});
myApp.directive('directiveTwo', function(){
return {
template: '<div></div>',
controller: function($rootScope){
$rootScope.$on('$locationChangeSuccess', function(){
console.log('Directive two callback');
});
}
}
});
在此代码中,您将仅看到记录的第二条日志消息,而我希望这两个指令都记录一条消息。
如何解决这个问题?我知道我可以进行构建,将模板添加到 $templateCache,但这是我的开发计算机,我不想每次都进行构建。
最佳答案
要理解这个问题,您需要了解 Angular 指令的生命周期和 ui-router
的架构.
问题是template
和templateUrl
Angular 的指令。是什么让这更有趣,你正在听$locationChangeSuccess
在指令的 Controller 函数中。
所以答案是因为指令加载了它的 templateUrl
异步。这意味着 Angular 不会等待 templateUrl 完全加载(因为如果这样做,它将停止整个引导过程)。因此它继续遍历 DOM 节点,并继续在管道中执行它应该执行的操作。这当然包括加载 Controller 、触发事件、进入特定状态等。
现在如果广播$locationChangeSuccess
在指令完全加载之前触发,它将错过这个特定事件,因此,您将错过 console.log
但是,如果有新的$locationChangeSuccess
加载指令之后再次发生(包括完成获取 templateUrl、实例化其自己的作用域等),那么是的,您的控制台日志应该再次捕获它。
我相信你的例子,有$locationChangeSuccess
仅发生一次,即在应用程序初始加载期间实例化 url。如果你真的强制另一个$locationChangeSuccess
加载 DOM 后,您的第一个指令将能够再次捕获该广播事件。
同样的道理,为什么 template = "<div></div>"
会起作用是因为该指令不需要异步获取它,因此当场编译,并且 DOM 在 $locationChangeSuccess
之前渲染。事件,并且能够控制台记录消息。
为了证明我的答案,我创建了一个 plnkr 。我正在使用$stateChangeSuccess
在 plnkr 中,但你明白了要点。在这里,我手动触发另一个 stateChange
通过单击按钮,这发生在加载指令之后。瞧,它捕捉到了广播!
TLDR:templateUrl
异步取, catch locationChangeSuccess
的车已经晚了.
希望这有帮助。
关于AngularJS - 如何在事件触发之前等待模板加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32720058/