弹出窗口关闭时如何删除扩展弹出窗口(React 组件)的侦听器?
How to remove a listener of an extension popup (React component), when the popup is closed?
我有一个用 React 构建的扩展(遗留代码),我一直在跟踪一个我终于解决了的错误,但我无法修复。
单击扩展图标(在浏览器栏中)时,会创建一个反应 Component
,并在其 componentDidMount()
中添加一个侦听器:
async componentDidMount(){
...
// an object from the background is retrieved
let background_object = this.props.getBackgroundObject();
...
// code including await background_object.doSomething();
...
// add event (eventemitter3 is used for the event management)
background_object.event.on('onMusic', this.dance);
...
}
async dance() {
this.setState({
'music': true,
})
}
但是,一旦 Component
消失,我不知道如何删除监听器,例如通过单击浏览器中的其他位置。我以为 componentWillUnmount
是我要找的东西,但它从来没有被称为:
componentWillUnmount(){
// this is never called!!!
background_object.event.removeListener('onDance', this.dance);
}
问题是每次我打开(和关闭)扩展弹出窗口时,都会向 background_object
添加一个新事件,因此 dance()
会被多次调用(与我打开的次数一样多)并关闭弹出窗口)。
目前,我使用 once
而不是 on
:
async componentDidMount(){
...
// an object from the background is retrieved
let background_object = this.props.getBackgroundObject();
...
// code including await background_object.doSomething();
...
// add event (eventemitter3 is used for the event management)
background_object.event.once('onMusic', this.dance);
...
}
async dance() {
// add the event again in case onMusic is called again
background_object.event.once('onMusic', this.dance);
this.setState({
'music': true,
})
}
这样一来,至少只调用了一次。但是,我担心 我的组件被多次创建 并在我的浏览器中消耗内存。
如何确保组件确实被销毁了?如何检测弹出窗口何时关闭以删除事件?
可以为此使用 chrome.runtime.onConnect
(感谢@wOxxOm):
- 在 React 组件的构造函数中打开一个连接:
constructor(props){
super(props)
this.state = {
dance: false,
}
...
var port = this.xbrowser.runtime.connect();
...
}
- 在react组件的
componentDidMount
中添加事件
async componentDidMount(){
...
// an object from the background is retrieved
let background_object = this.props.getBackgroundObject();
...
// add event (eventemitter3 is used for the event management)
background_object.event.on('onMusic', this.dance);
...
}
async dance() {
this.setState({
'music': true,
})
}
- 在后台某处(例如
background.js
)监听与浏览器的连接,并在连接丢失时删除事件:
chrome.runtime.onConnect.addListener(function (externalPort) {
externalPort.onDisconnect.addListener(function () {
let background_object = this.props.getBackgroundObject();
background_object.event.removeListener('onSend');
})
})
在我看来,这不是很优雅,但它确实有用。
我有一个用 React 构建的扩展(遗留代码),我一直在跟踪一个我终于解决了的错误,但我无法修复。
单击扩展图标(在浏览器栏中)时,会创建一个反应 Component
,并在其 componentDidMount()
中添加一个侦听器:
async componentDidMount(){
...
// an object from the background is retrieved
let background_object = this.props.getBackgroundObject();
...
// code including await background_object.doSomething();
...
// add event (eventemitter3 is used for the event management)
background_object.event.on('onMusic', this.dance);
...
}
async dance() {
this.setState({
'music': true,
})
}
但是,一旦 Component
消失,我不知道如何删除监听器,例如通过单击浏览器中的其他位置。我以为 componentWillUnmount
是我要找的东西,但它从来没有被称为:
componentWillUnmount(){
// this is never called!!!
background_object.event.removeListener('onDance', this.dance);
}
问题是每次我打开(和关闭)扩展弹出窗口时,都会向 background_object
添加一个新事件,因此 dance()
会被多次调用(与我打开的次数一样多)并关闭弹出窗口)。
目前,我使用 once
而不是 on
:
async componentDidMount(){
...
// an object from the background is retrieved
let background_object = this.props.getBackgroundObject();
...
// code including await background_object.doSomething();
...
// add event (eventemitter3 is used for the event management)
background_object.event.once('onMusic', this.dance);
...
}
async dance() {
// add the event again in case onMusic is called again
background_object.event.once('onMusic', this.dance);
this.setState({
'music': true,
})
}
这样一来,至少只调用了一次。但是,我担心 我的组件被多次创建 并在我的浏览器中消耗内存。
如何确保组件确实被销毁了?如何检测弹出窗口何时关闭以删除事件?
可以为此使用 chrome.runtime.onConnect
(感谢@wOxxOm):
- 在 React 组件的构造函数中打开一个连接:
constructor(props){
super(props)
this.state = {
dance: false,
}
...
var port = this.xbrowser.runtime.connect();
...
}
- 在react组件的
componentDidMount
中添加事件
async componentDidMount(){
...
// an object from the background is retrieved
let background_object = this.props.getBackgroundObject();
...
// add event (eventemitter3 is used for the event management)
background_object.event.on('onMusic', this.dance);
...
}
async dance() {
this.setState({
'music': true,
})
}
- 在后台某处(例如
background.js
)监听与浏览器的连接,并在连接丢失时删除事件:
chrome.runtime.onConnect.addListener(function (externalPort) {
externalPort.onDisconnect.addListener(function () {
let background_object = this.props.getBackgroundObject();
background_object.event.removeListener('onSend');
})
})
在我看来,这不是很优雅,但它确实有用。