Pertanyaan AngularJS directive $ destroy


Saya memiliki pengaturan aplikasi sudut dengan ng-view. Dalam satu tampilan, selain tampilan itu sendiri, ada juga komponen di dalam tampilan yang dimuat secara dinamis. Komponen ini adalah arahan yang pada dasarnya mengkompilasi isi sehingga isinya dapat lebih lanjut dikaitkan dengan arahan lain (yang mana). Konten di dalam komponen itu dikompilasi menggunakan $compile(element.contents())(scope);.

Sebagai contoh:

<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);
      }
    );
  };
}]);

Masalah saya adalah ketika saya berpindah rute, saya pada dasarnya beralih ng-view atauviewerisi. Masalah yang saya hadapi adalah kebocoran memori, di mana dalam arahan lain di dalam viewer kait ke acara dan tidak membersihkan saat rute diubah.

Salah satu contohnya adalah sebagai berikut:

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();
      });
    }
  };
}]);

Bagaimana saya memilikinya sehingga acara ini dibersihkan dengan benar?

Terima kasih.


32
2018-06-19 23:28


asal


Jawaban:


Contoh i18n yang Anda berikan akan berfungsi jika Anda hanya pernah menggunakannya sekali.

Saya tidak berpikir Anda harus melakukan acara yang mengikat di dalam fungsi kompilasi. Anda dapat melakukannya di dalam fungsi tautan sebagai gantinya:

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();
      });
    }
  };
}]);

Atau, Anda bisa mengikat acara pada lingkup anak itu sendiri, dan menggunakan $ broadcast pada $ rootScope untuk memicu itu. Dengan begitu, acara akan secara otomatis menjadi sampah yang dikumpulkan ketika ruang lingkup dihancurkan:

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');

45
2018-06-19 23:44