Javascript 如何在AngularJS中阻止$observe
我最近在Angular指令中的jQuery插件出现了一些问题,没有正确清理,因此造成了内存泄漏 所以,今天,当我在进行测试以确保不会发生这种情况时,我意识到没有办法停止观察Javascript 如何在AngularJS中阻止$observe,javascript,angularjs,angularjs-directive,Javascript,Angularjs,Angularjs Directive,我最近在Angular指令中的jQuery插件出现了一些问题,没有正确清理,因此造成了内存泄漏 所以,今天,当我在进行测试以确保不会发生这种情况时,我意识到没有办法停止观察 var stopObserving = attrs.$observe('myProperty', function(newValue) { updateElement(newValue); }); 因为我认为它的工作方式和它在$watch上的工作方式一样,但显然不是这样。根据文档,$observe将
var stopObserving = attrs.$observe('myProperty', function(newValue) {
updateElement(newValue);
});
因为我认为它的工作方式和它在$watch
上的工作方式一样,但显然不是这样。根据文档,$observe
将返回回调函数,即第二个参数
我有这个测试:
describe('destroy',function(){
beforeEach(function(){
$scope.$destroy();
});
it('should have emptied the DOM node', function(){
expect(element.text()).toBe('');
});
it('shouldn\'t have any more watchers', function(){
dump(element.data().$scope.$$watchers);
expect(element.data().$scope.$$watchers.length).toBe(0);
});
});
它失败了,因为只有一个观察者。我已经检查过了,正在调用$destroy
,因此,清理工作已经完成。然而,我怎样才能摆脱那个观察者呢
如果您感到好奇,代码如下:
AngularJS 1.3及以上版本
在Angular 1.3及以上版本中,取消注册$observe的工作方式与$watch完全相同:
var stopObserving = attrs.$observe(...);
stopObserving();
AngularJS 1.2及以下版本
在AngularJs 1.2中,无法取消注册观察者,正如您正确指出的,$observe返回回调函数
然而,目前有一个PR开放,可以更改$observe,以返回一个类似于$watch和$on的注销功能,不幸的是,由于出现了突破性的更改,这只在1.3版本中进行了试用。公共关系结束:
好消息是,按照的,实现更改需要整整3行新代码,因此如果您不能等到1.3版本,您可以自己轻松地实现它。当您调用$watch()方法创建绑定时,AngularJS返回一个“注销”函数。然后,可以使用此函数解除$watch()侦听器的绑定-只需调用此返回函数,即可删除$watch()侦听器。
要查看此操作,请查看以下代码。在这个演示中,我们将观察链接收到的点击次数。如果这个数字超过5,我们将显示一条消息;但是,一旦消息显示出来,我们就会删除侦听器,因为它不再有任何值
访问:
如您所见,我们正在存储$watch()语句返回的函数引用;然后,一旦$watch()触发几次,我们就会调用该存储方法,解除$watch()侦听器的绑定。如果查看console日志,可以看到console.log()语句在调用“注销”函数后立即停止。作为临时解决方案,您可以执行以下操作:
var key = 'myAttr';
attrs.$observe(key, function(newValue) {
updateElement(newValue);
delete attrs.$$observers[key];
});
或者如果你真的想变得漂亮:
attrs.$observe = function(key, fn) {
attrs.$observe(key, fn);
return function() {
delete attrs.$$observers[key];
};
}
var unobserve = attrs.$observe('myAttr', function(newValue){
updateElement(newValue);
unobserve();
});
那么,我可以从
$$watchers
数组中删除该函数吗?或者,listeners
是一些不可访问的代码吗?在测试中,您确定在beforeach中销毁的$scope与element.data().$scope是同一个$scope吗?您是否检查了dump($scope.$$watchers)
和expect($scope.$$watchers.length)。toBe(0)
?是的,我确定,因为我传递给$compile
的是范围
,以便创建指令元素。就像你之前建议的那样,但因为它不起作用,我想确保并改变这一点。。。我已经再试了一次,以防万一我忘了,它不起作用。如果我看不到你的代码,我就无能为力了。我建议你创建一个plunker来隔离问题并在你的问题中分享它,没有它我认为你不会得到太多帮助。我已经添加了一个指向Github repo的链接,因为它正在测试中。这与$observe
有什么关系?$observe和$watch做同样的事情。主要,$watch依赖于$parse(即,它接受有效AngularJS表达式的字符串,如“firstName+”+lastName”),并倾向于关注范围内的值,而$observe使用$interpolate(即,它接受包含{}}大括号的字符串,如“{{firstName}}{{lastName}}”),倾向于关注属性值,并且在使用attrs.$set时也会立即触发。我的问题的全部目的是说明,尽管它们是相同的,但在调用返回函数时却不相同。