2017-06-29 67 views
0

我有一个指令,它的回调看起来是这样的:仍然广播毁坏的控制器范围angularjs

function Callback(){ 
    return { 
     templateUrl: 'somePath', 
     scope: true, 
     link: function(scope, el) { 
     scope.cancel = function(){ 
      el.remove() 
      scope.$destroy() 
     } 
     }, 
     controller: 'someController', 
     controllerAs: 'vm' 
    } 
    } 

的联系方法,只是增加了一个cancel方法,可以消除DOM中的指令。

在指令控制器我听一个事件:

$rootScope.$on('parent', function(){ 
    someService.addToArray(someData) 
}) 

这种方法只是将数据推到一个数组。

在父控制器和视图中,这个指令被利用的地方我实际上正在发射广播。父控制器的一部分:

var vm = this 
vm.broadcastEvent = broadcastEvent  
function broadcastEvent(){ 
    $rootScope.$broadcast('someEvent', 'someData') 
} 

而在视图中,我有一些可点击的div触发此方法。

它工作得很好,该指令听到广播并将数据添加到数组之前,我删除元素并销毁范围。

问题是,在我调用.cancel后,该元素被删除,据推测该范围被销毁,但它仍然向数组添加数据。我是否错过了scope.$destroy()的工作原理?

我可以通过注销$on来获得我想要的行为,我是否需要这样做?我想问题是,是否销毁控制器范围取消了在其中定义的任何$on,或者是否需要确保在销毁范围之前明确注销?

回答

1

侦听功能是登记在$ rootScope和指令$范围后才能生存被销毁:

$rootScope.$on('parent', function listener(){ 
    someService.addToArray(someData) 
}) 

该控制器需要保存调用返回的注销函数到$ rootScope 。$上的方法:

this.deregister = $rootScope.$on('parent', function listener(){ 
    someService.addToArray(someData) 
}) 

的取消功能需要调用注销功能:范围被销毁前

link: function(scope, el) { 
    scope.cancel = function(){ 
     el.remove() 
     scope.$destroy() 
     scope.vm.deregister() 
    } 
    }, 
    controller: 'someController', 
    controllerAs: 'vm' 

不应该注销发生呢?

没关系。正如您发现的那样,因为侦听器已在$ rootScope上注册,它将存储在$ rootScope(特别是$rootScope.$$listeners)上的数组上。它通过调用取消注册功能从$rootScope.$$listeners中删除。

它是面向对象的运行时这种JavaScript的本质,即只有当对象的所有引用都被销毁时才从内存中移除对象(垃圾收集)。由于对listener函数的引用存储在$ rootScope中,因此它(及其执行上下文)仍然存在。

如果侦听器已在指令$ scope中注册,那么当范围被销毁时它会自动取消注册。

+0

是的,这正是我最终做的事情,而且当我写这个问题时它更有意义。像往常一样感谢@georgeawg! –

+0

在范围销毁之前不应该取消注册吗? –

0

我不确定scope.$destroy()是否正确调用。

因为它在$scope Doc的写道:

删除从父 范围的电流范围(及其所有的孩子)。 [...]请注意,在AngularJS中,还有一个$ destroy jQuery 事件,该事件可用于清除DOM绑定,然后从DOM中删除元素 。

所以,我认为你应该做它想:

link: function(scope, el) { 
     el.on('$destroy', function() { 
      scope.$destroy(); 
     }); 

     scope.cancel = function(){ 
      el.remove(); 
     } 
     } 

告诉我,如果它解决您的问题

相关问题