我已经看到很多指令性的例子,包括
AngularUI team那些他们似乎没有做任何清理的例子.
这是他们的ui-date指令的一个例子,它创建了一个jQuery datepicker.
(source)
element.on('blur',function() { ... });
他们在元素上放置了一个事件处理程序,但它们从来没有取消绑定事件.我原以为会有代码存在,例如:
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 });
所以这让我想知道是否有一些我不理解的东西.在这个指令被一遍又一遍地创建和销毁的情况下,他们所做的不会导致内存泄漏吗?
我错过了什么?
解决方法
理想情况下,您应该清除附加到链接到指令的元素以外的元素的任何事件处理程序.
例如,如果在您的指令中有一个窗口调整大小函数来修改指令的元素,则需要在销毁指令时删除窗口调整大小事件.
这是我必须构建的示例指令,您可以看到我必须解除绑定在指令范围之外的事件处理程序:
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)}); } }; } } });