【问题标题】:What should I do before removing a DOM element in AngularJS?在 AngularJS 中删除 DOM 元素之前我应该​​做什么?
【发布时间】:2017-03-15 07:33:09
【问题描述】:

我记得听说过在从 DOM 中删除元素之前需要销毁它的作用域。但我不完全确定这是如何完成的。

所以,碰巧我有一个从 DOM 中删除元素的指令。精简版如下所示:

(function() {
    angular.module('app').directive('remove', function() {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                element.children().remove();
                element.remove();
            }
        }
    }]);
}());

一个简单且不切实际的例子是这样的 <my-directive-with-isolated-scope remove></my-directive-with-isolated-scope>

我可以删除元素,但似乎范围没有被破坏,我相信这会造成内存泄漏,对吧?我还在指令的控制器(具有隔离范围的控制器)中设置了一个$interval,在那里我设置了一条控制台消息作为测试输出。而且我可以看到,当它从 DOM 中删除时,它仍然会在设置的时间间隔内注销一条控制台消息。

我是否需要修改上述指令中的某些内容才能正确删除元素?

【问题讨论】:

    标签: javascript angularjs dom angularjs-directive angularjs-scope


    【解决方案1】:

    您可以尝试使用元素/范围破坏进行一些实验:

    您可以进行测试以查看作用域何时被破坏,如下所示:

    scope.$on('$destroy', function(){
        console.log('Scope Destroyed!');
    });
    

    您还可以测试被销毁的元素:

    element.on('$destroy', function(){
        console.log('Element Destroyed!');
    });
    

    (请参阅angular.element docs事件部分)

    现在,关于间隔:

    $interval 将一直运行,直到你 $interval.cancel() 它,无论范围是否存在(除非回调是绑定到 scope 的某个函数,在这种情况下,回调可能会变为未定义,我不确定如何$interval 处理)。

    如果您的指令正在运行 $interval 函数,您可能会遇到类似的情况:

    var count = 0;
    var timer = 
        $interval( function doingStuff () {
            console.log( count + ' seconds ...' );
        }, 1000 );
    
    scope.$on('$destroy', function cleanup () {
        $interval.cancel( timer );
    });
    

    关于需要手动销毁作用域:

    如果您通过var myScope = $scope.$new(); 手动创建范围,则您有责任通过myScope.$destroy(); 销毁它。我会说这是一种更高级的用法,我想不出任何真正常见的手动创建新范围的原因。 (也许如果您的指令是创建一个元素并 $compile 它具有全新的范围)

    【讨论】:

      【解决方案2】:

      如果元素是从范围生成的,您应该销毁它,删除范围数据并让 Angular 重新渲染它,而不是使用 DOM 操作。范围数据与 DOM 元素本身无关,元素只是基于范围呈现的内容。所以删除一个元素不会对作用域变量产生任何影响。

      您不应该使用指令来执行此操作;改为更改或删除范围中的值。

      【讨论】:

        【解决方案3】:

        ng-viewng-ifng-repeatng-include等向DOM添加元素的指令,首先创建一个子作用域,然后使用$compile服务编译和链接这些元素在将它们附加到 DOM 之前,添加到该子范围。这些编译的元素链接到创建的子范围。当这些指令随后删除这些元素时,它们也会破坏子范围。

        创建子作用域:

        var childScope = scope.$new();
        

        要销毁该子范围:

        childScope.$destroy();
        

        有关详细信息,请参阅AngularJS rootScope.scope API Reference

        【讨论】:

          猜你喜欢
          • 2015-02-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-11
          • 1970-01-01
          • 2014-04-29
          • 1970-01-01
          相关资源
          最近更新 更多