首页 > 解决方案 > 控制器的实例未被删除

问题描述

我们正在开发一个 SPA,其中有一个带有自己的控制器的主页,并且在其中有一个使用以下内容构建的多选项卡窗格排列:

<div class="tab-content clearfix">
    <div class="tab-pane" 
         ng-repeat="One_Tab in Running_Tabs" 
         id="{{One_Tab.Page_Type}}_{{One_Tab.Instance}}" 
         ng-include="Build_Page_Reference(One_Tab.Page_Type)">
    </div>
</div>        

如下所述,问题在于一旦从屏幕上移除选项卡,其控制器实例仍处于活动状态。

每当用户单击命令菜单条目时,都会添加一个新元素,$scope.Running_Tabs然后显示新选项卡。当然,每个选项卡都由其自己的控制器处理。用户可能会打开不同的页面以及同一页面的不同实例,每个实例都有自己的上下文(例如,想象查看不同应用程序用户的配置文件)。

当用户希望关闭特定选项卡时,他单击主页控制器管理的选项卡上的“X”。然后,所有打开的选项卡的控制器都会发出和接收“关闭”事件。每个选项卡的控制器检查事件是否针对它(使用 Tab_ID)。如果不是,请忽略该事件。如果是,则进行控制器本地清理,完成后,将调用用于实际删除选项卡的通用功能(见下文)并将选项卡从屏幕上删除。

以下是处理实际选项卡删除的常用函数的代码(基于以下帖子:AngularJS not cleaning child scope created by ng-include):

function LLF_Remove_Tab (p_Tabs_Collection_Root , p_Tab_ID) {

    var l_Object ;

    for (var i = 0 ; i < p_Tabs_Collection_Root.length ; i++) {

        if (p_Tabs_Collection_Root[i].Tab_ID == p_Tab_ID) {

            l_Object = document.getElementById(p_Tabs_Collection_Root[i].Page_Type + "_" + 
                                               p_Tabs_Collection_Root[i].Instance) ;

            p_Tabs_Collection_Root.splice(i,1) ;

            angular.element(l_Object).scope().$destroy();

            l_Object.remove();

            break ;
        }
    }
}

问题是被移除的控制器的上下文仍然保持活跃。I added a simple console.logwhich is invoked when the tab receives the emmited close request (before checking if it is relevant or not). 之前使用上述功能删除的所有选项卡仍然会在接收事件时登录到控制台(因此很有可能会有多个具有相同 Tab_ID 的选项卡试图关闭)。

所以问题是:上述函数中缺少什么来确保完全删除关闭的选项卡的整个上下文。或者,我应该以不同的方式实现它吗?

标签: javascriptangularjs

解决方案


我不确定您为什么要尝试手动删除,而简单的方法应该可行:

主要的HTML:

<div class="tab-pane" ng-repeat="One_Tab in Running_Tabs" ng-include="One_Tab.template">
</div>

主控制器:

var vm = this;
vm.removeTab = (tab) => {
    var index = vm.Running_Tabs.indexOf(tab);
    vm.Running_Tabs.splice(index, 1);
}

选项卡模板示例:

<button ng-click="removeTab(One_Tab)">Close</button>

PS 另请注意,在模板中使用方法通常是个坏主意,因此最好创建 Tab 对象(例如 {}),计算模板并将其分配为 const 属性(例如 {template: 'template1.html'})。


推荐阅读