在 Template.onDestroyed 中删除 window 事件侦听器
Removing a window event listener in Template.onDestroyed
我有两个模板,每个模板都包含一个 Vimeo iframe
播放器。我正在使用 FlowRouter 通过主布局上的 {{> Template.dynamic template=main}}
呈现模板。
在两个模板中,我都为 onCreated
中的视频事件添加了监听器
Template.view.onCreated( function() {
var self = this;
if (window.addEventListener) {
window.addEventListener('message', function(event) {
viewMessageReceived(event, self)}, false);
} else {
window.attachEvent('onmessage', function(event){
viewMessageReceived(event, self)}, false);
}
});
并在 onDestroyed
中摧毁它们
Template.view.onDestroyed( function() {
if (window.removeEventListener) {
console.log('view remove');
window.removeEventListener('message', function(event) {
viewMessageReceived(event, self)}, false);
} else {
window.detachEvent('onmessage', function(event){
viewMessageReceived(event, self)}, false);
}
});
这是匿名事件处理程序调用的函数:
function viewMessageReceived(event, self) {
// Handle messages from the vimeo player only
if (!(/^https?:\/\/player.vimeo.com/).test(event.origin)) {
return false;
}
if (self.playerOrigin === '*') {
self.playerOrigin = event.origin;
}
var data = JSON.parse(event.data);
switch (data.event) {
case "ready":
initializePlayer(self);
break;
case "playProgress":
self.playerTime.set(data.data.seconds);
if (self.duration === '*') self.duration = data.data.duration;
break;
case "play":
self.playerStatus.set("playing");
break;
case "pause":
self.playerStatus.set("paused");
break;
}
}
当我切换到不同的模板时,onDestroyed
运行并且我的 console.log('view remove')
触发,如预期的那样。
但是,当我导航到使用视频播放器加载其他模板的页面时, 中的事件处理程序接收到 Vimeo "playProgress" message
previous 视频模板,该模板早就应该被删除了。这会抛出一个错误,因为之前的模板已经被破坏了。
Uncaught TypeError: Cannot read property 'contentWindow' of undefined
来自这个函数的最后一行:
function post(template, action, value) {
console.log('view action: %s value: %s', action, value);
var data = {method: action};
if (value) data.value = value;
var message = JSON.stringify(data);
template.player[0].contentWindow.postMessage(message, template.playerOrigin);
}
每个包含视频的模板都有自己的 .js 文件,因此它们都有自己的 post
函数声明。我的理解是,定义函数的方式是将函数的范围限制在页面范围内。
只有一条消息发给了错误的玩家。之后,他们到达当前加载的播放器。
为什么 Vimeo 消息事件在我已经销毁模板并转移到另一个播放器后到达或得到处理?
W3School 网站关于 removeEventListener()
方法的引用:
// Attach an event handler to <div>
document.getElementById("myDIV").addEventListener("mousemove", myFunction);
// Remove the event handler from <div>
document.getElementById("myDIV").removeEventListener("mousemove", myFunction);
Note: To remove event handlers, the function specified with the
addEventListener() method must be an external function, like in the
example above (myFunction).
Anonymous functions, like "element.removeEventListener("event",
function(){ myScript });" will not work.
为此,您需要将函数定义移动到 onRendered
和 onDestroyed
事件之外的某处,并且只需在 add/remove 事件中传递函数名称听众。
我有两个模板,每个模板都包含一个 Vimeo iframe
播放器。我正在使用 FlowRouter 通过主布局上的 {{> Template.dynamic template=main}}
呈现模板。
在两个模板中,我都为 onCreated
Template.view.onCreated( function() {
var self = this;
if (window.addEventListener) {
window.addEventListener('message', function(event) {
viewMessageReceived(event, self)}, false);
} else {
window.attachEvent('onmessage', function(event){
viewMessageReceived(event, self)}, false);
}
});
并在 onDestroyed
Template.view.onDestroyed( function() {
if (window.removeEventListener) {
console.log('view remove');
window.removeEventListener('message', function(event) {
viewMessageReceived(event, self)}, false);
} else {
window.detachEvent('onmessage', function(event){
viewMessageReceived(event, self)}, false);
}
});
这是匿名事件处理程序调用的函数:
function viewMessageReceived(event, self) {
// Handle messages from the vimeo player only
if (!(/^https?:\/\/player.vimeo.com/).test(event.origin)) {
return false;
}
if (self.playerOrigin === '*') {
self.playerOrigin = event.origin;
}
var data = JSON.parse(event.data);
switch (data.event) {
case "ready":
initializePlayer(self);
break;
case "playProgress":
self.playerTime.set(data.data.seconds);
if (self.duration === '*') self.duration = data.data.duration;
break;
case "play":
self.playerStatus.set("playing");
break;
case "pause":
self.playerStatus.set("paused");
break;
}
}
当我切换到不同的模板时,onDestroyed
运行并且我的 console.log('view remove')
触发,如预期的那样。
但是,当我导航到使用视频播放器加载其他模板的页面时, 中的事件处理程序接收到 Vimeo "playProgress" message
previous 视频模板,该模板早就应该被删除了。这会抛出一个错误,因为之前的模板已经被破坏了。
Uncaught TypeError: Cannot read property 'contentWindow' of undefined
来自这个函数的最后一行:
function post(template, action, value) {
console.log('view action: %s value: %s', action, value);
var data = {method: action};
if (value) data.value = value;
var message = JSON.stringify(data);
template.player[0].contentWindow.postMessage(message, template.playerOrigin);
}
每个包含视频的模板都有自己的 .js 文件,因此它们都有自己的 post
函数声明。我的理解是,定义函数的方式是将函数的范围限制在页面范围内。
只有一条消息发给了错误的玩家。之后,他们到达当前加载的播放器。
为什么 Vimeo 消息事件在我已经销毁模板并转移到另一个播放器后到达或得到处理?
W3School 网站关于 removeEventListener()
方法的引用:
// Attach an event handler to <div>
document.getElementById("myDIV").addEventListener("mousemove", myFunction);
// Remove the event handler from <div>
document.getElementById("myDIV").removeEventListener("mousemove", myFunction);
Note: To remove event handlers, the function specified with the addEventListener() method must be an external function, like in the example above (myFunction).
Anonymous functions, like "element.removeEventListener("event", function(){ myScript });" will not work.
为此,您需要将函数定义移动到 onRendered
和 onDestroyed
事件之外的某处,并且只需在 add/remove 事件中传递函数名称听众。