简单地说我的情况是我从运行阶段开始一个事件。在几个指令中,我听这个事件并执行代码。问题是在我的开发机器上,一些指令在编译指令之前通过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的构建,但这是我的开发机器,我不想每次都进行构建。
答案 0 :(得分:2)
要理解这个问题,您需要了解角度指令的生命周期 AND ui-router
的架构。
该指令的捕捉是template
和templateUrl
。更有趣的是,你正在听指令的控制器函数中的$locationChangeSuccess
。
所以答案是因为指令加载templateUrl
异步。这意味着angular不会等待templateUrl完全加载(因为如果它,它将停止整个引导过程)。因此它继续遍历DOM节点,并继续在管道中应该做的任何事情。这当然包括加载控制器和火灾事件,进入特定状态等等。
现在如果$locationChangeSuccess
的广播在之前触发指令完全加载,它将错过这个特定事件,因此,你将错过console.log
但是,如果新的$locationChangeSuccess
再次发生 后加载指令(包括完成获取templateUrl,实例化自己的范围等),那么是的,您的控制台日志应该是再次抓住它。
我相信你的例子,$locationChangeSuccess
只发生一次,这是在你的应用程序的初始加载期间,其中url被实例化。如果在加载DOM后实际强制另一个$locationChangeSuccess
,则第一个指令将能够再次捕获该广播事件。
出于同样的原因,为什么template = "<div></div>"
将起作用是因为该指令不需要异步获取它,因此在现场编译,并且DOM在$locationChangeSuccess
事件之前呈现,并且能够控制台记录消息。
为了展示我的答案,我创建了一个plnkr。我在plnkr中使用$stateChangeSuccess
,但你得到了要点。在这里,我通过单击按钮手动触发另一个stateChange
,这在 指令加载后发生。瞧,它接收了广播!
TLDR:templateUrl
是异步获取的,赶上locationChangeSuccess
的火车已经很晚了。
希望这有帮助。
答案 1 :(得分:0)
指令被懒散地加载。我不相信angular会在运行阶段评估你的任何指令。你能详细说明你的要求吗?