原型中的绑定事件处理程序仍然保持对元素的引用

时间:2009-11-11 17:04:06

标签: javascript events prototypejs

我希望能够在原型中使用绑定事件处理程序并保留我的“this”上下文。但这样做似乎会破坏原型提供事件处理程序的方便的默认绑定。

来自文档:

  

处理程序的上下文(此值)设置为被观察的扩展元素(即使事件实际发生在后代元素上并冒泡)。

这正是我想要的。一旦我将函数绑定到我自己的上下文,我可以以任何方式访问这个“被观察的元素”吗?我不能依赖e.element()来给我观察到的元素(它可能是一个子元素):

initialize: function() {
     Event.observe('foo', 'click', this.addItem.bind(this));
},

...

addItem: function(e) {
   e.element() // -> clicked element, not necessarily observed element
}

我知道有一个bindAsEventListener,但这里似乎没有必要,一旦绑定了函数,我就看不到如何访问目标元素。

我也知道有一个e.currentTarget,但这在IE中不起作用,是吗?

2 个答案:

答案 0 :(得分:2)

当您使用.bind时,将覆盖您通过this对被观察元素的引用。如果您有以下标记:

<div id="foo">
    I am the Foo
    <button id="bar">I am the Bar</button>
</div>

不使用.bind,您可以访问观察到的&amp;像这样的射击元素:

function greenEggsAndHam (evt) {
    console.log('Observed Element: %o', this);
    console.log('Clicked Element: %o', $(evt.element()));
}
Event.observe('foo', 'click', greenEggsAndHam);

但是,如果要使用类方法作为事件处理程序,因此需要使用.bind,那么解决方案是将观察到的元素的标识符作为事件处理程序的参数之一包含在内首先绑定事件,如下所示:

var Test = Class.create({
    initialize: function() {
        Event.observe('foo', 'click', this.greenEggsAndHam.bind(this, 'foo'));
    },
    greenEggsAndHam: function (el, evt) {
        console.log('Observed Element: %o', $(el));
        console.log('Clicked Element: %o', $(evt.element()));
        console.log('Class reference: %o', this);
    }
});
var T = new Test();

这就是说,为了保持一致性,我建议您使用.bindAsEventListener而不是.bind,并将事件处理程序更改为function (evt, el) {,以便事件对象是第一个参数,观察到的元素是第二个。

答案 1 :(得分:0)

我最近也遇到过这个问题。我的回答是将函数包装在另一个完成所需工作的函数中。我可能搞砸了订单但curry会将this添加到匿名函数的args中,然后从那里重新订购。

initialize: function() {
  Event.observe('foo', 'click', 
    function(e,that) { that.addItem(e,this); }.curry(this)
    );
  },
addItem: function(evt, evtElm) {
  ...
  }