2016-12-28 4 views
1

角度アプリは、index.htmlにng-viewディレクティブで設定し、$ routeProvider設定と各ビューに独自のコントローラを設定します。あるView Controllerでは、イベントを監視する$ rootScope。$がリスナーにあります。ビューを変更したときにこのリスナーが動作しなくなると思っていますが、そうではありません。たとえそのコントローラをもはや使用していないビューに切り替えた場合でも、時計はトリガされたときにコードを呼び出し続けます。

$ destroyイベントを聴くためのテストコードをいくつか設定しましたが、$ destroyイベントがトリガーされていますが、リスナー関数は引き続き実行されています。ウォッチ関数と$ destroyイベントリスナの両方で$ scope。$ idを出力しましたが、IDが一致していることがわかります。したがって、特定のスコープに対して$ destroyイベントが発生した後でも、$ onリスナーがまだ実行されているようです。これはなぜですか?私は、別のビューに移動したり、コントローラが破棄されたりすると、そのリスナーがクリアされるという印象を受けました。

Plnkr:http://plnkr.co/edit/TxssxQJY5PVLTAIAr4xD?p=preview

var animateApp = angular.module('animateApp', ['ngRoute', 'ngAnimate']); 

animateApp.config(function($routeProvider) { 
    $routeProvider 
     .when('/', { 
      templateUrl: 'page-home.html', 
      controller: 'mainController' 
     }) 
     .when('/about', { 
      templateUrl: 'page-about.html', 
      controller: 'aboutController' 
     }) 
     .when('/contact', { 
      templateUrl: 'page-contact.html', 
      controller: 'contactController' 
     }); 

}); 

angular.module('animateApp').service('service', ['$interval', '$rootScope', service]); 
function service ($interval, $rootScope) { 
    var service = {}; 
    service.abc = 1; 
     $interval(function() { 
     service.abc++; 
     $rootScope.$broadcast('service.abc', service.abc); 
    }, 500); 

    return service; 

} 


animateApp.controller('mainController', function($scope, $rootScope, service) { 
    $scope.pageClass = 'page-home'; 
    $scope.$on('$destroy', function iVeBeenDismissed() { 
         console.log('goodbye ' + $scope.$id); 
     // release resources, cancel request... 
    }) 

    $rootScope.$on('service.abc', function (newval) { 
     console.log($scope.$id); 
    }) 
}); 

animateApp.controller('aboutController', function($scope) { 
    $scope.pageClass = 'page-about'; 
}); 

animateApp.controller('contactController', function($scope) { 
    $scope.pageClass = 'page-contact'; 
}); 
+1

[plunk](http://plnkr.co)または[fiddle](http://jsfiddle.net) – Minato

+0

[mcve] – TheSharpieOne

+0

を入力してください申し訳ありませんが、実際は$ rootScope。$をリスナーで使用します。私はplnkrで更新して編集します。 – dz210

答えて

0

あなたのコントローラで$destroyイベントリスナーを追加する必要があります。これにより

scope.$on('$destroy', function() { 
     element.off('blur'); // example 
     element = null; 
    }); 

を手動にはより積極的な$ウォッチャーがないことを確認してくださいよ非アクティブなコントローラ。

3

質問が完全に変更されてコンテキストが完全に異なるようになったので、これまでの回答は全く同じように適用されます

以下の回答と同じ点でリスナーの登録を解除できます。

$rootScope.$on()は、登録解除機能を返します。

したがって、あなたのmainControllerのように書き換えることができます。

animateApp.controller('mainController', function($scope, $rootScope, service) { 
    $scope.pageClass = 'page-home'; 
    var unregister = $rootScope.$on('service.abc', function (newval) { 
     console.log($scope.$id); 
    }); 
    $scope.$on('$destroy', function iVeBeenDismissed() { 
     unregister(); 
    }); 
}); 

前の回答

あなたは、コントローラのスコープが破棄されたとき、あなたの時計をバインド解除することを確認する必要があります。

時計を作成すると、作成した時計のアンバインド機能が返されます。これはかなりよくカバーされていますhere

作成した時計への参照を作成します。

var unbinder = $scope.$watch("foo.bar", doStuff); 

はあなたがあったように、あなたの範囲の破壊に注意、しかしそこにあなたのunbinderを呼び出します。

$scope.$on("$destroy", function(){ 
    if(typeof unbinder === "function") 
     unbinder(); 
}); 

unbinder関数が呼び出されると、時計は削除されます。

+0

@ dz210あなたの変更に合わせて私の答えを再検討してください。今後、より具体的な質問をしてください。 – WebWanderer

+0

応答をありがとうが、私の質問は具体的にコントローラが破壊されて表示された後にリスナーを実行し続けているので、私は解決策を探していないが起こっているものの説明です。残念ながら、私はすでにリスナーと腕時計の登録を解除する方法を知っています。角度のある文書で答えを見つけることができなかったので、私の質問はより理論的です。 – dz210

+0

それから@ dz210あなたの答えはあなたのアプリケーション全体に対して '$ rootScope'がグローバルであり、' $ rootScope'に対してリスナーを登録することは、あなたが手作業で行う場合を除き、孤立したスコープに対するバインディングを持たないことです。 '$ scope。$ on'のように孤立したスコープにリスナーを置くのであれば、そのスコープが存在するときにリスナーが破棄されます。あなたの質問は、なぜあなたが思っている以上のことが不思議に思うのかを特定するものではありません。 – WebWanderer

関連する問題