避免多次添加事件监听器

Avoid from adding event listeners several times

我有一个 Office 加载项,可以通过

打开弹出式浏览器 window
popup = window.open("https://localhost:3000/#/new", "popup", "status=1, location=1, width=1000, height=1200")

此页面由 angular 编码。为了启用加载项和弹出窗口之间的通信,我在控制器中添加了一个侦听器。因此,他们可以通过 postMessage.

互相发送消息
app.controller("Ctrl", ["$scope", "$window", function($scope, $window) {
    ... ...
    $window.addEventListener("message", receiveMessage, false);
}

通信有效,除非加载项将弹出窗口的 url 更改为 newUrl(其中 newUrl 是使用同一控制器的另一个页面实例),通过

popup.location.href = newUrl

从视觉上看,弹出窗口已更改,但未删除之前的侦听器。因此,加载项发送的一条消息会被接收和处理两次(即,新页面和上一页)。

有谁知道加载项更改弹出页面时如何正确清理侦听器?

this.receiveMessage = function(e){
  ...
}
$window.addEventListener("message", this.receiveMessage, {once: true, capture: false});

Cenk 的评论是正确的:事件删除和事件添加逻辑必须在完全相同的函数范围内。

因此,在加载项方面,当弹出窗口更改为另一个 Url 时,我需要通过 postMessage 手动向页面发送 close 消息:

popup.postMessage({ "req": "close" }, popup.location.href);
popup.location.href = url

在弹出页面的一侧,我可以删除 receiveMessage 中的侦听器,因为它仍在相同的 page/function 范围内:

app.controller("Ctrl", ["$scope", "$window", function($scope, $window) {
    ... ...
    var receiveMessage = function (event) {
        ... ...
        switch (event.data) {
            ... ...
            case "close": 
                $window.removeEventListener("message", receiveMessage, false)
        }
    }
}])