范围未被删除

时间:2015-02-25 21:57:39

标签: angularjs controller angularjs-scope ondestroy

使用角度1.2.9

解释工作原理:      我在网页左侧有一个列表,用户可以按+按钮将视图附加到.viewSpace。

当用户按下

angular.element(document.getElementById('viewSpace')).append($compile("<div my-graph></div>")(scope));

被调用。 my-graph是一个使用类似

的模板的指令
<div ng-controller="MyGraphController" id="{{viewId}}">
...
</div>

viewId是在实例化时创建的,该id被传递给一个服务,该服务跟踪视图并广播更改,以便左视图可以知道使用新按钮更新列表以删除刚刚添加的元素。 remove指令如下所示:

app.directive("removeView", function($compile){
    return function(scope, element, attrs){
        element.bind("click", function(){
            var id = '#'+attrs.removeView; // id of view to remove when clicked
            console.log('Removing', id);
            angular.element(id).parent().remove();
            //angular.element(document.getElementById(attrs.tseRemoveView)).remove();
            $compile(".viewSpace");
        });
    };
});

和图形控制器cconsists of destroy function。

chartApp.controller('MyGraphController', function ($scope, $interval, controllerService) {
    $scope.cid = controllerService.getCurrentControllerId();
    $scope.viewId = controllerService.createViewId($scope.cid);
    controllerService.bindToViewList($scope.viewId, "Linear Graph");// for view communication.

    $scope.$on("$destroy", function() { // never gets called.
        console.log('destroying cid', $scope.cid);
        resetGraph(); // the intervals will persist after controller instance is destroyed, so take care of them onDestroy
        controllerService.removeBindToViewList($scope.viewId, "Linear Graph");
    });
});

问题:图形从DOM中消失但范围仍然存在,并且永远不会调用destroy函数。有什么想法吗?

chartApp.directive('myGraph', function($rootScope, $window) {
    return {
        restrict: 'EA',
        templateUrl: 'myGraph.tpl.html',
        scope: {}, 
        link: function(scope, elem, attrs) {
            elem.on('$destroy', function(){// does get called though
                alert('elem destroyed');
            });
        }
    };
});

controllerService函数,用于共享范围内的视图数据:

this.bindToViewList = function(id, viewType){
        console.debug('bindToViewList', id, viewType);
        if(viewType in views){
            views[viewType].push(id);
        }else{
            views[viewType]=[id];
        }
        broadcastViewUpdate();
    }

    this.removeBindToViewList = function(id, viewType){
        console.debug('removeBindToViewList', id, viewType);
        var index = views[viewType].indexOf(id);
        views[viewType].splice(index, 1);
        broadcastViewUpdate();
    }

1 个答案:

答案 0 :(得分:0)

简短的回答是,当删除元素时,Angular不会自动调用$ destroy。您必须明确地调用它(https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope):

  当需要将作用域及其子作用域与父作用域永久分离并因此通过调用停止参与模型更改检测和侦听器通知时,必须在作用域上调用$ destroy()。

更多信息:http://www.bennadel.com/blog/2706-always-trigger-the-destroy-event-before-removing-elements-in-angularjs-directives.htm

此外,您的设计似乎在很大程度上依赖于DOM而不是连接模型并让Angular处理与DOM的交互。看起来你可以为你的视图空间提供一个指令,使用ng-repeat渲染和数组视图,然后在用户单击 - 按钮时调用splice()来删除视图。 Angular将处理DOM,你不必执行任何jQuery,因为angular会删除从数组中删除的DOM中的任何内容。