2017-06-29 69 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(); 
     } 
     } 

告訴我,如果它解決您的問題

相關問題