I've seen a lot of directive examples including those by the AngularUI team where they don't appear to do any cleanup.
我已经看过很多指令性的例子,包括AngularUI团队的例子,他们似乎没有做任何清理工作。
Here's an example from their ui-date directive which creates a jQuery datepicker. (source)
这是他们的ui-date指令的一个例子,它创建了一个jQuery datepicker。 (资源)
element.on('blur', function() { ... });
They placed an event handler on the element, but at no point do they ever unbind the event. I would have expected there to be code present such as:
他们在元素上放置了一个事件处理程序,但它们从来没有取消绑定事件。我原以为会有代码存在,例如:
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
});
So this makes me wonder if there's something I don't understand. Wouldn't what they are doing cause a memory leak in situations where the element w/ this directive is created and destroyed over and over?
所以这让我想知道是否有一些我不理解的东西。在这个指令被一遍又一遍地创建和销毁的情况下,他们所做的不会导致内存泄漏吗?
What am I missing?
我错过了什么?
1 个解决方案
#1
6
Yes ideally you should clean up any event handlers that are attached to elements other than the element linked to the directive.
理想情况下,您应该清除附加到链接到指令的元素以外的元素的任何事件处理程序。
Fore example if in your directive you have a window resize function to modify the element of the directive you will need to remove the window resize event when the directive is destroyed.
例如,如果在您的指令中有一个窗口调整大小函数来修改指令的元素,则需要在销毁指令时删除窗口调整大小事件。
here's an example directive I had to build and you can see I had to unbind the event handlers attached outside of the scope of the directive:
这是我必须构建的示例指令,您可以看到我必须解除绑定在指令范围之外的事件处理程序:
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)});
}
};
}
}
});
#1
6
Yes ideally you should clean up any event handlers that are attached to elements other than the element linked to the directive.
理想情况下,您应该清除附加到链接到指令的元素以外的元素的任何事件处理程序。
Fore example if in your directive you have a window resize function to modify the element of the directive you will need to remove the window resize event when the directive is destroyed.
例如,如果在您的指令中有一个窗口调整大小函数来修改指令的元素,则需要在销毁指令时删除窗口调整大小事件。
here's an example directive I had to build and you can see I had to unbind the event handlers attached outside of the scope of the directive:
这是我必须构建的示例指令,您可以看到我必须解除绑定在指令范围之外的事件处理程序:
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)});
}
};
}
}
});