我看过很多指令性的例子,包括AngularUI team那些他们似乎没有做任何清理的例子。
这是他们创建jQuery日期选择器的ui-date指令的示例。 (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
});
所以这让我想知道是否有一些我不理解的东西。在这个指令被一遍又一遍地创建和销毁的情况下,他们所做的不会导致内存泄漏吗?
我错过了什么?
答案 0 :(得分:6)
是的,理想情况下,您应该清除附加到链接到指令的元素以外的元素的任何事件处理程序。
例如,如果在你的指令中你有一个窗口调整大小函数来修改指令的元素,你需要在指令被销毁时删除window resize事件。
这是我必须构建的示例指令,你可以看到我必须解除绑定在指令范围之外的事件处理程序:
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)});
}
};
}
}
});