如何安全地清理指令中的AngularJS事件绑定
How to safely clean up AngularJS event binding in a directive
我有一个Angular指令,它将元素的高度设置为浏览器窗口的内部高度(+/-给定的偏移量)。此指令响应窗口的"调整大小"事件并相应地调整其高度。当我的指令的作用域发出"$destory"事件时,我会删除与"resize"事件的绑定(我认为保留它会导致一些问题,如果我错了,请纠正我)。
我不知道如何以一种"安全"的方式完成这项活动。如果我在整个应用程序中有多个该指令的实例,如果我有附加到"调整大小"事件的其他指令,该怎么办?
JQuery有事件名称空间的概念,这似乎是一个很好的解决方案,但Angular的实现(JQLite)不支持这一点。我宁愿不使用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
};
UPDATE看起来像是RTFM的一个例子,但为了防止其他人在这里闲逛,这里有一些更多信息。将原始函数(在我的例子中是OnResize
)传递给.off()
可以隔离.off()
函数的作用域。来自文档:
也可以通过在处理程序参数中指定函数名来删除处理程序。当jQuery{ahem…JQLite}附加一个事件处理程序时,它会为处理程序函数分配一个唯一的id。
这是我指令中更新的cleanUp
函数:
cleanUp = function () {
window.angular.element($window).off('resize', onResize);
};
感谢tasseKATT、Karolis和Hans的贡献。
向off
传递与传递给on
:相同的函数引用
window.angular.element($window).off('resize', onResize);
代替:
window.angular.element($window).off('resize');
演示-将函数引用传递到off:http://plnkr.co/edit/1rfVPNXl6TrEcuYvzPAj?p=preview
演示-不将函数引用传递到off:http://plnkr.co/edit/IsLqSLAzNcHqDnhMty7Q?p=preview
演示包含两个指令,这两个指令都在侦听窗口大小调整事件。在代码和预览之间使用垂直分隔符来触发事件。
你会注意到,如果你破坏了其中一个,那么在将函数引用传递到off时,另一个将继续工作。如果你不这样做,两者都将停止工作。
几周前我也有同样的问题。
查看jqLite源代码后(https://github.com/angular/angular.js/blob/master/src/jqLite.js),我们看到on
方法通过jqLiteOff
函数添加事件,off
方法删除事件。
更深入地看,我们看到jqLiteRemoveData
调用jqLiteOff
。CCD_ 12由CCD_。jqLiteDealoc
在几个地方被调用:jqLiteEmpty
、html
、replaceWith
和remove
。jqLiteEmpty
被分配给元素的empty
方法,该方法清除jQuery中的元素。html
、replaceWith
和remove
是jQuery模拟。
搜索元素上调用remove()
的位置,我们可以看到它被用于大多数(如果不是全部的话)DOM操作逻辑。您可以在ngIf
、ngSwitch
、ngInclude
和ngView
中看到它。
因此,我认为Angular确实可以处理事件侦听器清理,只要您使用jqLite附加事件,并在自己的DOM操作逻辑中适当地调用remove()
。使用jQuery包装一个元素会打乱很多过程,包括事件侦听器清理,但我想您已经完全意识到了这一点,因为您使用的是angular.element
。
首先,将JQuery和AngularJS一起使用绝对没有错。
除此之外,我喜欢做的是有一个body
指令,它侦听window.on('resize', ...)
并将大小写入$rootScope.windowSize
。然后在元素上有另一个指令,即$watch("windowSize", ...)
,并根据需要设置为width。(实际上不必在$scope
中公开大小,而是可以使用require
)。
- 一次显示一个隐藏指令-AngularJS
- 一次显示一个指令AngularJS
- 在同一页面上多次使用的自定义指令 (AngularJS) 中的验证
- 无法绑定到没有指令 + angularjs 标识符的控制器
- 值未传递给指令-AngularJS
- 测试依赖于另一个指令Angularjs的指令
- 根据指令angularjs 1.2分配控制器
- 有模板问题的指令.AngularJS
- 编译指令在指令 AngularJS 中
- 我可以将 templateUrl 传递给指令 - AngularJS
- 从子指令的父指令 [angularJS] 触发子指令中的函数
- 将服务注入指令 AngularJS 和数据绑定
- 在指令 AngularJS 中解析
- 从指令 AngularJS 给出高图表正确的参数
- 获取 JSON 数据并传递给指令 Angularjs
- 点击事件后的渲染模板指令 - AngularJs
- 如何从分页指令angularjs隐藏直接页面链接
- AngularJS-关闭tile并从ngRepeat指令AngularJS中的模型加载新视图
- 触发指令AngularJs的控制器作用域
- 将定义的对象传递给另一个自定义指令angularjs