Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在AngularJS中阻止$observe_Javascript_Angularjs_Angularjs Directive - Fatal编程技术网

Javascript 如何在AngularJS中阻止$observe

Javascript 如何在AngularJS中阻止$observe,javascript,angularjs,angularjs-directive,Javascript,Angularjs,Angularjs Directive,我最近在Angular指令中的jQuery插件出现了一些问题,没有正确清理,因此造成了内存泄漏 所以,今天,当我在进行测试以确保不会发生这种情况时,我意识到没有办法停止观察 var stopObserving = attrs.$observe('myProperty', function(newValue) { updateElement(newValue); }); 因为我认为它的工作方式和它在$watch上的工作方式一样,但显然不是这样。根据文档,$observe将

我最近在Angular指令中的jQuery插件出现了一些问题,没有正确清理,因此造成了内存泄漏

所以,今天,当我在进行测试以确保不会发生这种情况时,我意识到没有办法停止观察

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时也会立即触发。我的问题的全部目的是说明,尽管它们是相同的,但在调用返回函数时却不相同。