取消订阅范围内的所有事件是否安全。$ destroy?

时间:2017-02-09 12:57:44

标签: javascript angularjs

我发现了一个如下的AngularJS指令:

function MyDirective() {
    return {
        restrict: 'A',
        link: function(scope, elem) {
            elem.on('click', function() {
                // do stuff
            });
            scope.$on('$destroy', function () {
                elem.off('click');
            });
        }
    };
}

我特别担心以下部分:

elem.off('click');

是否可以安全地假设在scope.$destroy之后元素将不再被使用,我们可以简单地清除所有侦听器,而不仅仅是这个特定指令添加的侦听器?

2 个答案:

答案 0 :(得分:2)

  

范围销毁 - 当不再需要子范围时,它就是   子范围创建者的责任是通过它来销毁它们   范围。$摧毁()API。这样做是为了阻止传播   $ digest调用子范围并允许使用的内存   垃圾收集器回收的子范围模型。

     

自动清理注册到范围和元素的监听器   当它们被摧毁时,但是如果你注册了一个听众   服务,或在未存在的DOM节点上注册侦听器   删除,你必须自己清理它或你冒险介绍一个   记忆泄漏。

有关angular.element的更多信息 https://docs.angularjs.org/api/ng/function/angular.element

范围破坏已经处理了通过可用的AngularJS directives添加的事件破坏(例如ng-click /`ng-change'/ ....)

使用ng-...指令将自动执行销毁。使用自定义事件/侦听器时,请始终在$destroy事件时手动删除它们。

是的我会声明解除所有指令(不是应用程序作用域处理程序)处理程序是安全的,因为scope无论如何都会被销毁。您的元素属于ng-controller范围(destroyed),因此不再需要。事实上,无论如何,Angular对你的影响更深......

答案 1 :(得分:1)

那么它取决于您取消订阅该事件的元素。恕我直言在取消订阅活动时应始终保持谨慎。我记得我的一个项目,其中我错误地取消订阅了click事件,该事件在项目中引入了微妙的错误并让我感到悲惨。在您的情况下,您的指令很小而且干净。

function MyDirective() {
    return {
        restrict: 'A',
        link: function(scope, elem) {
            elem.on('click', function() {
                // do stuff
            });
            scope.$on('$destroy', function () {
                elem.off('click');
            });
        }
    };
}

因此,当它的范围被销毁时,该元素将根本不存在于视图中,并且当Daan突出显示时,注册到范围和元素的侦听器在被销毁时会自动清理所以我们不必为注册的监听器而烦恼,因为一旦元素被重新创建,监听器将再次注册,在你的情况下click到元素。但是,如果您想要删除您注册的听众并不是所有听众,那么您可以namespace您的活动,然后订阅和取消订阅它们:

//Subscribing
angular.element("#element")
  .on("click.myNamespace", function() { 
     console.log("doSomething");
   });
//Unsubscribing
$("#element").off("click.myNamespace");

Here's CSS技巧文章谈论namespacing虽然它基于jQuery,但概念是相同的。