我有一个Angular指令,它将元素的高度设置为等于浏览器窗口的内部高度(+/-给定的偏移量)。该指令响应窗口"调整大小"事件并相应调整其高度。当我的指令范围发出' $ destory'事件,我删除绑定到"调整大小"事件(我认为将它留在原地会引起一些问题,如果我错了,请纠正我)。
我不知道如何在" safe"中做这个事件分离。办法。如果我在我的应用程序中有多个此指令实例,如果我有其他指令附加到'调整大小,该怎么办?事件?
JQuery具有事件命名空间的概念,这似乎是一个很好的解决方案,但Angular的实现(JQLite)does not support this。我不想使用JQuery,因为我已经使用了Angular,所以我该怎么办?
这是我今天指令的代码
window.angular.module('arcFillClient', [])
.directive('arcFillClientY', ['$window',
function ($window) {
function link($scope, el, attrs) {
var setHeight,
onResize,
cleanUp;
setHeight = function (offSetY) {
var newHeight;
offSetY = offSetY || 0;
newHeight = Math.max($window.innerHeight + parseInt(offSetY, 10)) + 'px';
el.height(newHeight);
};
onResize = function () {
var offset;
offset = attrs.arcFillClientY || 0;
setHeight(offset);
};
attrs.$observe('arcFillClientY', setHeight);
window.angular.element($window).on('resize', onResize);
cleanUp = function () {
window.angular.element($window).off('resize');
};
$scope.$on('$destroy', cleanUp);
}
return {
link: link
};
更新看起来像RTFM的情况,但万一其他人徘徊在这里,这里有更多信息。将原始函数(在我的情况下为OnResize
)传递给.off()
可以隔离.off()
函数的范围。来自docs:
也可以通过在handler参数中指定函数名来删除处理程序。当jQuery {ahem ... JQLite}附加一个事件处理程序时,它会为处理函数赋予一个唯一的id。
这是我指令中更新的cleanUp
函数:
cleanUp = function () {
window.angular.element($window).off('resize', onResize);
};
感谢tasseKATT,Karolis和Hans的贡献。
答案 0 :(得分:28)
在传递给off
时将相同的函数引用传递给on
:
window.angular.element($window).off('resize', onResize);
而不是:
window.angular.element($window).off('resize');
演示 - 将函数引用传递给关闭:http://plnkr.co/edit/1rfVPNXl6TrEcuYvzPAj?p=preview
演示 - 未将函数引用传递给关闭:http://plnkr.co/edit/IsLqSLAzNcHqDnhMty7Q?p=preview
演示包含两个指令,都监听窗口调整大小事件。使用代码和预览之间的垂直分隔符来触发事件。
你会注意到,如果你销毁了一个,那么当将函数引用传递给off时,另一个将继续工作。如果你不这样做,两者都会停止工作。
答案 1 :(得分:5)
几个星期前,我有同样的问题。
查看jqLite源代码(https://github.com/angular/angular.js/blob/master/src/jqLite.js)后,我们发现on
方法添加了事件,off
方法通过jqLiteOff
函数删除了事件。
仔细观察,我们看到jqLiteRemoveData
来电jqLiteOff
。 jqLiteRemoveData
调用jqLiteDealoc
。 jqLiteDealoc
会在jqLiteEmpty
,html
,replaceWith
和remove
中调用jqLiteEmpty
。 empty
被赋值给元素的html
方法,该方法清除了jQuery中的元素。 replaceWith
,remove
和remove()
是jQuery模仿。
搜索在元素上调用ngIf
的位置,我们看到它在大多数(如果不是全部)DOM操作逻辑上使用。您可以在ngSwitch
,ngInclude
,ngView
和remove()
中看到它。
所以我认为Angular会处理事件监听器清理,只要你使用jqLite附加事件并在你自己的DOM操作逻辑中适当地调用angular.element
。使用jQuery包装元素会搞砸很多进程,包括事件监听器清理,但我想你已经完全清楚了,因为你使用的是{{1}}。
答案 2 :(得分:2)
首先,使用JQuery和AngularJS绝对没有错。
除此之外,我喜欢做的是body
指令,它会监听window.on('resize', ...)
并将大小写入$rootScope.windowSize
。然后在元素上有另一个指令,$watch("windowSize", ...)
并根据需要设置为width。 (您实际上不必在$scope
中公开大小 - 您可以使用require
)。