简体   繁体   English

避免多次添加事件侦听器

[英]Avoid from adding event listeners several times

I have an Office add-in which can open a popup browser window by 我有一个Office加载项,可以通过以下方式打开弹出浏览器窗口

popup = window.open("https://localhost:3000/#/new", "popup", "status=1, location=1, width=1000, height=1200")

This page is coded by angular. 该页面按角度编码。 To enable the communication between the add-in and the popup, I have added a listener in the controller. 为了启用外接程序和弹出窗口之间的通信,我在控制器中添加了一个侦听器。 As a result, they can send messages to each other by postMessage . 结果,他们可以通过postMessage相互发送消息。

app.controller("Ctrl", ["$scope", "$window", function($scope, $window) {
    ... ...
    $window.addEventListener("message", receiveMessage, false);
}

The communication works, except when the add-in changes the url of the popup to newUrl (where newUrl is another page instance which uses the same controller), by 除外接程序将弹出窗口的URL更改为newUrl (其中newUrl是使用同一控制器的另一个页面实例)外,通信均有效。

popup.location.href = newUrl

Visually, the popup has changed, however the previous listener is not removed . 外观上,弹出窗口已更改,但是先前的侦听器未删除 As a result, one message sent by the add-in is received and treated twice (ie, by the new page and the previous page). 结果,外接程序发送的一条消息被接收并处理了两次(即,新页面和上一页)。

Does anyone know how to properly clean the listener when the add-in changes the popup page? 加载项更改弹出页面时,有人知道如何正确清理侦听器吗?

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

The comment of Cenk is correct: the event-remove and event-add logic must be in exactly the same function scope. Cenk的评论是正确的:事件删除和事件添加逻辑必须在完全相同的功能范围内。

So, on the side of the add-in, when the popup changes to another Url, I need to send manually a close message by postMessage to the page: 因此,在外接程序一侧,当弹出窗口更改为另一个URL时,我需要通过postMessage手动向页面发送close消息:

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

On the side of the popup page, I could remove the listener in the receiveMessage , because it is still in the same page/function scope: 在弹出页面的一侧,我可以在receiveMessage删除侦听器,因为它仍在同一页面/函数范围内:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM