7

Ho visto molti esempi di direttive, compresi quelli dello AngularUI team, in cui non sembra che vengano effettuati interventi di pulizia.

Ecco un esempio della direttiva ui-date che crea un datepicker jQuery. (source)

element.on('blur', function() { ... }); 

hanno messo un gestore di eventi sull'elemento, ma in nessun punto fanno mai UNBIND l'evento. Mi sarei aspettato che ci fosse del codice come:

var namespace = ".uiDate"; 

element.on('blur' + namespace, function() { ... }); 
element.on("$destroy" + namespace, function() 
{ 
    element.datepicker("destroy");  //Destroy datepicker widget 
    element.off(namespace);    //Unbind events from this namespace 
}); 

Quindi questo mi chiede se c'è qualcosa che non capisco. Non farebbe quello che stanno facendo una perdita di memoria in situazioni in cui l'elemento w/questa direttiva viene creato e distrutto più e più volte?

Cosa mi manca?

+0

Una domanda simile con una risposta molto utile: http://stackoverflow.com/questions/26983696/angularjs-does-destroy-remove-event-listeners – hgoebl

risposta

6

Sì, idealmente, è necessario pulire tutti i gestori di eventi che sono collegati a elementi diversi dall'elemento collegato alla direttiva.

In questo esempio, se nella direttiva si dispone di una funzione di ridimensionamento della finestra per modificare l'elemento della direttiva, sarà necessario rimuovere l'evento di ridimensionamento della finestra quando la direttiva viene distrutta.

ecco una direttiva ad esempio ho dovuto costruire e si può vedere ho dovuto separare i gestori di eventi collegati al di fuori del campo di applicazione della direttiva:

lrApp.directive('columnArrow',function($timeout){ 
    return { 
    restrict : 'A', 
    scope : { 
     active : '=columnArrow' 
    }, 
    link: function($scope, elem, attrs, controller) { 
     $scope.$watch('active',function(){ 
      $timeout(function(){ 
      adjust(); 
      },0); 
     }); 

     $(window).resize(adjust); 

     elem.parents('.column-content').scroll(adjust); 

     $scope.$on('$destroy', function() { 
      elem.removeClass('hide'); 
      elem.parents('.column-content').unbind('scroll',adjust); 
      $(window).unbind('resize',adjust); 
     }); 

     function adjust(e) { 
      if($scope.active) { 
      var parentScroll = elem.parents('.column-content'); 
      var parent = elem.parent(); 
      var visible = inView(parentScroll[0],parent[0]); 
      if(!visible) { 
       elem.addClass('hide'); 
      } else { 
       elem.removeClass('hide'); 
      } 
      var offset = parent.offset(); 
      var w = parent.outerWidth(); 
      var h = (parent.outerHeight()/2) - (elem.outerHeight()/2); 
      elem.css({'top':offset.top + h,'left':offset.left + (w + 5)}); 
      } 
     }; 

    } 
    } 
}); 
+0

Come vengono rimossi i gestori di eventi sull'elemento w/la direttiva allegata? – CHS

+0

Potete vedere che rimuovo qualsiasi gestore di eventi nella funzione $ destroy e tutti gli altri eventi che sono collegati all'elemento stesso sono rimossi da angolare. Sono solo gli allegati a pensare al di fuori dell'ambito della direttiva che è necessario rimuovere – btm1

+0

Sei sicuro che gli ascoltatori dell'elemento non debbano essere rimossi? – CMCDragonkai