当 $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 行.它抱怨说由于状态变化,它无法找到 id
或 design-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
));
};
除了注销事件处理程序之外,代码还需要释放所有创建的对象引用。
为了让不同的组件相互通信,我在 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 行.它抱怨说由于状态变化,它无法找到 id
或 design-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
));
};
除了注销事件处理程序之外,代码还需要释放所有创建的对象引用。