【问题标题】:Event Handling in Javascript using Prototypal Inheritance使用原型继承在 Javascript 中进行事件处理
【发布时间】:2013-05-17 13:41:43
【问题描述】:

我正在尝试在 JavaScript 中启用事件处理。这是我目前所拥有的:

function Field(args) {
    this.id = args.id;

    this.name = args.name ? args.name : null;
    this.reqType = args.reqType ? args.reqType : null;
    this.reqUrl = args.reqUrl ? args.reqUrl : null;
    this.required = args.required ? true : false;
    this.error = args.error ? args.error : null;

    this.elem = document.getElementById(this.id);
    this.value = this.elem.value;

    this.elem.addEventListener('onblur', this, false);
    this.elem.addEventListener('click', this, false);
    this.elem.addEventListener('change', this, false);
    console.log(JSON.stringify(this.elem.value));

}

function FormTitle(args) {
    Field.call(this, args);
}

Field.prototype.getValue = function() { return Helpers.trim( this.value ) };

Field.prototype.sendRequest = function () {

};

Field.prototype.click = function (value) {
    alert("click");  
};

Field.prototype.onblur = function (value) {
    alert("onblur");  
};

Field.prototype.change = function (value) {
    alert("change");  
};

Field.prototype.dblclick = function (value) {
    alert("dblclick");  
};

Field.prototype.handleEvent = function(event) {
    switch (event.type) {
    case "click": this.click(this.value);
    case "onblur": this.onblur(this.value);
    case "change": this.change(this.value);
    case "dblclick": this.dblclick(this.value);
    }
};

// inheritProtootype uses parasitic inheritance to inherit from the Field's prototype
// and then assign the results to FormTitle's prototype.
inheritPrototype(FormTitle, Field);

var title = new FormTitle({name: "sa", id: "title"});

但是,由于某种原因,所有事件都会同时触发。例如,当我点击Form中的Title字段时,不是只触发Click事件,而是触发了所有四个事件。

我做错了什么?

【问题讨论】:

  • this.elem.addEventListener('…', this, false); 确实附加了 Field 实例,一个对象,作为事件侦听器 - 这需要是一个函数吗?

标签: javascript events javascript-events event-handling


【解决方案1】:

简单。在每个 case 块的末尾,使用 break; 语句将其与每个后续块分开。

【讨论】:

  • 你的答案是正确的。我不确定我在想什么!但是Bergi's 似乎比switch 语句更优雅。所以我选择了这个作为答案。顺便问一下,你知道为什么“onblur”事件可能不会触发吗?
  • @user 可能是因为在使用监听器注册时,您省略了“on”。所以请尝试addEventListener('blur', ...);
  • 好的,这样模糊就可以了。但最后一个问题。它(模糊)似乎被多次触发,包括当我第一次关注该领域时。然后当我切换窗口时也会触发它。你知道解决办法吗?
  • @user 对不起,不知道答案。切换窗口部分似乎是合法的,因为在退出浏览器焦点时该字段实际上是模糊的。但是,在聚焦领域时触发事件是不寻常的......
【解决方案2】:

您的switch 语句遗漏了一些break 语句,因此如果click 将执行所有四个方法。

但是,有一个比switch-statement 更好的选择:

Field.prototype.handleEvent = function(event) {
    var prop = event.type;
    if (prop in this) // && typeof this[prop] == "function"
        this[prop](this.value);
};

这将适用于所有事件而无需明确提及。

【讨论】:

  • 是的,这就像一个魅力。顺便问一下,你知道为什么“onblur”事件没有触发吗?
  • @user:因为事件被命名为blur :-) on 前缀仅适用于 M$ .attachEvent 和事件属性。
  • @user 这种事件处理方法绝对比switch 更好。解释这段代码的作用:in 关键字检查左侧表示的属性是否存在于右侧的指定对象中。 JavaScript 允许以“点表示法”和索引表示法访问属性。使用索引表示法,可以通过变量动态访问对象的属性。这种有效的方法允许简单地扩展事件,而无需修改列表等。
  • @user 顺便说一下,索引表示法与点表示法有些不同。索引也不是正确的词,因为它的符号更像是一张地图。基本上任何东西,包括对象,都可以作为键。这也意味着您可以拥有名为 foo bar 的属性,这对于点表示法是不可能的。真是个不错的功能……
  • @Derija93:这种类型的成员运算符被命名为bracket notation(只有数字我称之为index)。不,它仅适用于字符串;您传入的所有内容都被隐式字符串化
【解决方案3】:

在你的 switch 语句中,你需要在每个 case 后面加上一个break

switch (event.type) {
  case "click": this.click(this.value); break;
  case "onblur": this.onblur(this.value); break;
  case "change": this.change(this.value); break;
  case "dblclick": this.dblclick(this.value); break;
}

最后一个中断不是必需的,但最好包含它,因为您可能会添加其他案例。

【讨论】:

  • 您有正确的答案,但 Bergi 的解决方案非常优雅。谢谢!
猜你喜欢
  • 2012-10-31
  • 1970-01-01
  • 2011-03-02
  • 2012-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-28
  • 2018-02-21
相关资源
最近更新 更多