JavaScript 函数被事件侦听器多次调用,即使我引用了该函数
JavaScript function gets called multible times by event listener even though I reference the function
我每次创建 angular 控制器时都会添加一个事件侦听器。每次我离开此页面并返回时,都会添加一个新的事件侦听器,因为再次调用构造函数。
当这个事件被触发时,同一个事件被调用两次,如果我离开并回来,它被调用 3 次......等等。我只希望它总是被调用一次。
下面是添加事件监听器的代码,以及它调用的监听器函数:
(仅供参考,我正在使用 TypeScript)
在构造函数中:
this.$window.addEventListener("message", this.processApi, false);
调用函数:
processApi = (e) => {
this.processApiMessage(e.data);
};
我读到我应该调用对函数的引用而不是键入函数本身,因此两者都引用了同一个函数实例,但同一个事件侦听器被多次调用。
当我在 chrome 中使用开发人员工具并转到 EventListners 和消息部分时,每次点击构造函数时我都会看到一个新的 Window 元素。我可以通过开发人员工具删除每个 EventListers,但是当我这样做时似乎无法通过代码让它工作:
this.$window.removeEventListener("message", this.processApi, false);
我发现如果我刷新页面,所有事件侦听器都会清除,并且我在构造函数中创建的事件侦听器会正常工作。
我正在使用 angular,并使用 $location 服务导航到点击我的控制器的 url,因此快速修复是替换 $location.url( "url") 到 window.location.href("url")
这似乎有效,因为当我导航到页面时页面会刷新。我宁愿保留 $location 用于路由,即使 angular 构造函数被多次命中,我的事件监听器也只被命中一次。
当作用域为$destroyed
时,您需要移除事件侦听器。因此,在控制器构造函数中,您需要注入 $scope
对象。在构造函数中,做这样的事情:
$scope.$on('$destroy', () =>
$window.removeEventListener("message", this.processApi));
可以肯定的是,有多种创建控制器的方法。最常见的(特别是如果您使用的是 TypeScript)是为控制器创建一个 class。
我还会考虑将侦听器添加到 rootScope 而不是 $window,后者更像是 Angular 的处理方式。把它们放在一起,它看起来像这样:
class MyController {
constructor($rootScope, $scope) {
'ngInject';
let unsubscriber = $rootScope.$on('message', this.processApi, false);
$scope.$on('$destroy', () => unsubscriber());
}
...
}
我每次创建 angular 控制器时都会添加一个事件侦听器。每次我离开此页面并返回时,都会添加一个新的事件侦听器,因为再次调用构造函数。
当这个事件被触发时,同一个事件被调用两次,如果我离开并回来,它被调用 3 次......等等。我只希望它总是被调用一次。
下面是添加事件监听器的代码,以及它调用的监听器函数: (仅供参考,我正在使用 TypeScript)
在构造函数中:
this.$window.addEventListener("message", this.processApi, false);
调用函数:
processApi = (e) => {
this.processApiMessage(e.data);
};
我读到我应该调用对函数的引用而不是键入函数本身,因此两者都引用了同一个函数实例,但同一个事件侦听器被多次调用。
当我在 chrome 中使用开发人员工具并转到 EventListners 和消息部分时,每次点击构造函数时我都会看到一个新的 Window 元素。我可以通过开发人员工具删除每个 EventListers,但是当我这样做时似乎无法通过代码让它工作:
this.$window.removeEventListener("message", this.processApi, false);
我发现如果我刷新页面,所有事件侦听器都会清除,并且我在构造函数中创建的事件侦听器会正常工作。
我正在使用 angular,并使用 $location 服务导航到点击我的控制器的 url,因此快速修复是替换 $location.url( "url") 到 window.location.href("url")
这似乎有效,因为当我导航到页面时页面会刷新。我宁愿保留 $location 用于路由,即使 angular 构造函数被多次命中,我的事件监听器也只被命中一次。
当作用域为$destroyed
时,您需要移除事件侦听器。因此,在控制器构造函数中,您需要注入 $scope
对象。在构造函数中,做这样的事情:
$scope.$on('$destroy', () =>
$window.removeEventListener("message", this.processApi));
可以肯定的是,有多种创建控制器的方法。最常见的(特别是如果您使用的是 TypeScript)是为控制器创建一个 class。
我还会考虑将侦听器添加到 rootScope 而不是 $window,后者更像是 Angular 的处理方式。把它们放在一起,它看起来像这样:
class MyController {
constructor($rootScope, $scope) {
'ngInject';
let unsubscriber = $rootScope.$on('message', this.processApi, false);
$scope.$on('$destroy', () => unsubscriber());
}
...
}