在Template.onDestroyed中删除窗口事件侦听器

时间:2016-02-03 18:49:44

标签: meteor vimeo-api flow-router

我有两个模板,每个模板都包含一个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到达时由上一个视频模板中的事件处理程序接收,该模板本来应该已被删除。这会引发错误,因为之前的模板已被销毁。

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消息事件在我已经销毁模板并且我已经移动到其他播放器后到达或处理?

1 个答案:

答案 0 :(得分:0)

W3Schools网站关于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);
  

注意:要删除事件处理程序,请使用指定的函数   addEventListener()方法必须是一个外部函数,就像在   上面的例子(myFunction)。

     

匿名函数,例如&#34; element.removeEventListener(&#34; event&#34;,   function(){myScript});&#34;不行。

为此,您需要在onRenderedonDestroyed事件之外的某处移动函数定义,并在add / remove事件侦听器中传递函数名称。