范围未被删除

Scope not being removed

使用 angular 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 被传递给跟踪视图和广播更改的服务,以便左视图可以知道用新的 - 按钮更新列表以删除刚刚被删除的元素添加。删除指令如下所示:

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");
        });
    };
});

图形控制器由销毁函数组成。

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();
    }

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

$destroy() must be called on a scope when it is desired for the scope and its child scopes to be permanently detached from the parent and thus stop participating in model change detection and listener notification by invoking.

更多信息: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 中删除从数组中删除的任何内容。