更改$ state(UI路由器)时取消绑定eventListener

时间:2019-01-16 13:24:25

标签: angularjs angular-ui-router addeventlistener

为了使不同的组件能够互相通信,我在$emit方法中使用了service方法

服务代码:

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方法等待时加载了特定的$onInit(例如toolsState)此事件发生。

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控制器行的控制台外,其他所有操作均按预期进行。它抱怨说由于状态变化而找不到iddesign-select的元素。

在我看来,$scope的{​​{1}}的状态改变了,因此其toolsState方法仍在运行。

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

1 个答案:

答案 0 :(得分:0)

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

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

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

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