一旦我使用相同的代码将侦听器添加到另一个元素,事件侦听器似乎就消失了

时间:2011-11-06 19:06:31

标签: javascript events event-handling

所以,这已经困扰了我很长一段时间。

我有一个像这样的javascript构造函数:

function TimeBlock(c, local_count){
    /* creates a timeblock */
    .
    .
    .
    _getel(this.id).addEventListener('mouseover', this.displayPopup)
    _getel(this.id).addEventListener('mouseout', this.killPopup)
}

基本上它创建了一个TimeBlock对象并为它分配了两个事件处理程序,它们在TimeBlock.prototype中定义如下:

TimeBlock.prototype = {
    .
    .
    .
    block = getTimeBlock(e.target.id)
    //do something
    },

    killPopup: function(e){
    // //do something else
    }
}

它有效。我调用new Timeblock (some_parameters)并获取我的时间块,它将元素创建到html(它是一个div)并将侦听器分配给它。我测试它,它工作正常。但是一旦我再次调用它,我就会创建一个新的TimeBlock元素,使用工作的侦听器,但前一个停止工作。就像将这些侦听器分配到新元素上一样,取消应该在前一个元素上的侦听器。

甚至更奇怪的是,我已经通过javascript控制台手动分配了这些监听器,并且它在那里工作得很好。我正在使用Firefox 7.0.1和Firebug进行这些测试。

非常感谢

1 个答案:

答案 0 :(得分:0)

此代码可疑:

_getel(this.id).addEventListener('mouseover', this.displayPopup)

...因为虽然你把这个函数作为事件处理程序连接起来,但是你没有做任何事情来保留this在处理程序中的含义。因此,当调用处理程序时,this与上面的代码中的相同。我怀疑this意味着失去了什么导致你在尝试使用多个TimeBlock实例时所看到的效果。

有多种方法可以确保使用正确的this值调用函数,其中一个值如下所示:

function TimeBlock(c, local_count){
    /* creates a timeblock */
    .
    .
    .
    var self = this;
    _getel(this.id).addEventListener('mouseover', function(event) {
        self.displayPopup(event);
    });
    _getel(this.id).addEventListener('mouseout', function(event) {
        self.killPopup(event);
    });
}

更多阅读:

唯一想到的是mouseovermouseout 冒泡到父元素,如果你不小心,可能会让人感到困惑。例如,如果你有:

<div>Foo <span>bar</span></div>

...您在mouseover上关注mouseoutdiv,当鼠标从mouseout移动时,您会看到span( “bar”)进入div(“foo”),如果你不期待它,这可能会令人惊讶。


这是一个示例,演示了两个独立的实例,如上所述(live copy)连接到独立元素:

window.onload = function() {

    new TimeBlock("firstElement");
    new TimeBlock("secondElement");

    function _getel(id) {
      return document.getElementById(id);
    }

    function TimeBlock(id){
        var self = this;
        this.id = id;
        this.counter = 0;
        _getel(this.id).addEventListener('mouseover', function(event) {
            self.displayPopup(event, this);
        });
        _getel(this.id).addEventListener('mouseout', function(event) {
            self.killPopup(event, this);
        });
    }

    TimeBlock.prototype.displayPopup = function(event, element) {
        ++this.counter;
        element.innerHTML = "Display, counter = " + this.counter;
    };

    TimeBlock.prototype.killPopup = function(event, element) {
        element.innerHTML = "Remove, counter = " + this.counter;
    };

};