当 $state (ui-router) 改变时取消绑定 eventListener

Unbinding eventListener when a $state (ui-router) is changed

为了让不同的组件相互通信,我在 service

的方法中使用了 $emit 方法

服务代码:

this.triggerSelectedAction = function( actionName )
{
    $rootScope.$emit('action-changed', { actionName: actionName } );
};

this.triggerSelectedProject = function( projectName )
{
    $rootScope.$emit('project-changed', { projectName: projectName } );
};

this.triggerSelectedFile = function( fileName )
{
    $rootScope.$emit('file-changed', { fileName: fileName } );
};

this.subscribe = function( scope, cb )
{
    var eventHandler;
    eventHandler = $rootScope.$on('action-changed', cb);
    eventHandler = $rootScope.$on('project-changed', cb);
    eventHandler = $rootScope.$on('file-changed', cb);

    scope.$on( '$destroy', eventHandler );
};

现在假设我从应用程序内部的某处调用 myService.triggerSelectedAction('doSomething'); 并且当时加载了一个特定的 $state(例如 toolsState),其 $onInit 方法等待此事件发生。

toolsState 控制器$onInit代码:

myService.subscribe($scope, function eventOccured(event, data) {
    if ( event.name === "action-changed" )              
        setEnvironment();
});

function setEnvironment() {
    // Attach an event listener to the select element
    document
        .getElementById("design-select")
        .addEventListener("change", projectSelectedEvent);
}

现在假设我们改变一个状态,例如转到 manageState,它也在等待相同事件的发生并且具有类似的 $onInit 代码,除了它绑定了 eventListener 到不同的元素。

管理状态控制器$onInit代码:

myService.subscribe($scope, function eventOccured(event, data) {
    if ( event.name === "action-changed" )              
        setEnvironment();
});

function setEnvironment() {
    // Attach an event listener to the select element
    document
        .getElementById("manage-select")
        .addEventListener("change", projectSelectedEvent);
}

在这种情况下,如果事件被触发,一切都会按预期工作,除了我在控制台中得到一个 TypeError: Cannot read property 'addEventListener' of null,它引用带有 addEventListener 方法的 toolsState Controller 行.它抱怨说由于状态变化,它无法找到 iddesign-select 的元素。

对我来说,似乎 toolsState$scope 当状态改变时,它的 myService.subscribe() 方法仍然是 运行。

有什么方法可以消除这个错误。

每当代码将函数或对象传递给 API 时,都存在创建对象引用的风险,这将阻止垃圾回收。这可能会导致内存泄漏。

$on 方法 returns 一个函数,可用于取消绑定事件处理程序:

this.subscribe = function( scope, cb )
{
    var deRegister = {};
    deRegister.ActionChanged = $rootScope.$on('action-changed', cb);
    deRegister.ProjectChanged = $rootScope.$on('project-changed', cb);
    deRegister.FileChanged = $rootScope.$on('file-changed', cb);

    scope.$on( '$destroy', function() {
        deRegister.ActionChanged();
        deRegister.ProjectChanged();
        deRegister.FileChanged();
        deRegister = null; //release deRegister object
        scope = null;      //release scope reference
        cb = null;         //release callback function reference
    ));
};

除了注销事件处理程序之外,代码还需要释放所有创建的对象引用。