AngularJS指令$ destroy

时间:2013-06-19 23:28:56

标签: javascript angularjs angularjs-directive

我有一个带有ng-view的角度应用程序设置。在一个视图中,除了视图本身之外,该视图中还有一个动态加载的组件。该组件是一个基本上编译内容的指令,因此内容可以进一步与其他指令(它是)挂钩。该组件内的内容使用$compile(element.contents())(scope);进行编译。

举个例子:

<ng-view>
  <viewer doc="getDocument()">
  </viewer>
</ng-view>


angular.directive('viewer', ['$compile', '$anchorScroll', function($compile, $anchorScroll) {
  return function(scope, element, attrs) {
    scope.$watch(
      function(scope) {
        var doc = scope.$eval(attrs.doc);
        if (!doc)
          return ""

        return doc.html;
      },
      function(value) {
        element.html(value);
        $compile(element.contents())(scope);
      }
    );
  };
}]);

我的问题是当我切换路线时,我基本上会切换ng-viewviewer的内容。我遇到的问题是内存泄漏,viewer内的其他指令挂钩事件,并且在路由更改时不清理。

一个这样的例子如下:

angular.directive('i18n', ['$rootScope', 'LocaleService', function($rootScope, LocaleService) {
  var cleanup;
  return {
    restrict: 'EAC',
    compile: function(element, attrs) {
      var originalText = element.text();
      element.text(LocaleService.getTranslation(originalText, attrs.locale));
      cleanup = $rootScope.$on('locale-changed', function(locale) {
        element.text(LocaleService.getTranslation(originalText, attrs.locale || locale));
      });
    },
    link: function(scope) {
      scope.$on('$destroy', function() {
        console.log("destroy");
        cleanup();
      });
    }
  };
}]);

我如何才能正确清理这些事件?

感谢。

1 个答案:

答案 0 :(得分:48)

如果您只使用过一次,那么您提供的i18n示例将起作用。

我认为你不应该在编译函数中进行事件绑定。您可以在链接功能中执行此操作:

angular.directive('i18n', ['$rootScope', 'LocaleService', function($rootScope, LocaleService) {
  return {
    restrict: 'EAC',
    link: function(scope, element, attrs) {
      var cleanup;
      var originalText = element.text();
      element.text(LocaleService.getTranslation(originalText, attrs.locale));
      cleanup = $rootScope.$on('locale-changed', function(locale) {
        element.text(LocaleService.getTranslation(originalText, attrs.locale || locale));
      });
      scope.$on('$destroy', function() {
        console.log("destroy");
        cleanup();
      });
    }
  };
}]);

或者,您可以在子作用域本身上绑定事件,并使用$ rootScope上的$ broadcast来触发它。这样,当范围被销毁时,事件将自动被垃圾收集:

angular.directive('i18n', ['$rootScope', 'LocaleService', function($rootScope, LocaleService) {
  return {
    restrict: 'EAC',
    link: function(scope, element, attrs) {
      var originalText = element.text();
      setElText();
      function setElText(locale){
        element.text(LocaleService.getTranslation(originalText, attrs.locale || locale));
      }
      scope.$on('locale-changed', setElText);
    }
  };
}]);

$rootScope.$broadcast('locale-change', 'en-AU');