使用Mootools添加事件处理程序'.addEvent()会在某个地方神秘地失败

时间:2011-09-28 11:43:32

标签: javascript ajax mootools

我正在为一个网络应用程序正在研究一些JS,这是一个令人难以置信的问题。不幸的是,我无法发布完整的代码,因为它是尚未发布的项目的一部分。这个问题让我和我的一些同事难以理解 - 从我能说的,它应该有效。

现在,针对实际问题:用户在某些表单字段中输入一些信息并单击“确认”图像,然后将AJAX请求发送回服务器。服务器执行一些处理,然后发送回状态和一些附加数据的响应。状态消息显示在用户正在使用的模态对话窗口中,并显示带有链接的图标。这是Mootools Request.JSON对象的“onComplete”处理程序,删除了一些错误条件处理:

  onComplete: function(response) {
    if (response) {
      if (response.status == 0) {
        // this means the request was successful
        licenses = response.licenses;
        updateControls();
        licenseList();
        // here I add the status message...
        $("createform_result").innerHTML = "<img src=\'/media/com_supportarea/images/db_success.png\' /> License created. Download:<br /><br />";
        // ...and the download "link"
        if (response.tlsid) {
          $("createform_result").innerHTML += "<a href=\"#\" id=\"newtlslic-"+response.tlsid+"\"><img src=\'/media/com_supportarea/images/download_small.png\' /></a> <em>TLS</em>";
          // this line is here for debugging only, to make sure this
          // block of code is run (it is) and the element is found (it is)
          $("newtlslic-"+response.tlsid).style.border = "1px solid red";
          $("newtlslic-"+response.tlsid).addEvent("click", function(e) {
            // I've stripped out all other code, also for debugging
            e.stop();
          });
        }
      }
    }
  }

出现带有链接的消息和图标,应用样式(出现红色边框),Firefox或Chrome中不显示任何错误消息。但是,单击该图标会导致将#附加到URL(e.stop())不执行任何操作。根据EventBug插件,链接没有附加点击事件。似乎.addEvent()在这里什么都不做。

现在,他们在这里提出质疑:为什么会这样,我该如何解决?救命啊!

1 个答案:

答案 0 :(得分:1)

javascript中的

字符串是不可变的。当你做的事情:

$("createform_result").innerHTML += "<a href=\"#\" id=\"newtlslic-"+response.tlsid+"\"><img src=\'/media/com_supportarea/images/download_small.png\' /></a> <em>TLS</em>";

您将innerHTML引用为字符串。它的作用是,它将属性提取到一个字符串中,将它连接到你传递的其他字符串,然后在最后返回一个新字符串,将其设置为innerHTML。

这样做,每次迭代都会重写元素的内容。

附加到元素的事件不是由通用ID处理程序完成的 - 它们依赖于DOM中的元素,然后正在读取元素UID(内部属性mootools分配给所有传递的元素)并添加事件回调进入UID后面的元素存储。

您可以通过console.log(element.retrieve("events"));

查看此工作

如果重写innerHTML,则重新创建内部元素并获取NEW UID,这意味着回调现在指向空指针,因为UID是元素存储中的键。

我在这里做的事情可能是错的,因为我实际上没有看到你再次重写它的位,但是在你剥离的代码中可能有一个,特别是如果你正在运行一个循环。

处理此问题的最佳方法是使用事件委派。

它可以允许您通过某个选择器将click事件添加到父元素。这适用于任何匹配时以任何方式添加的元素。

例如

// add this once, outside the loop 
$("createform_result").addEvent("click:relay(a.editLink)", function(event, element) {
    console.log(this === element); 
    console.log(this === event.target);
    console.log(this.get("data-id"));
}); 

// then as you loop the results, just inject the els or use innerHTML or whatever...
new Element("a.editLink", {
    html: '<img src=\'/media/com_supportarea/images/download_small.png\' /></a> <em>TLS</em>',
    "data-id": response.tlsid
}).inject($("createform_result"));

事件委托现在是1.4.0中mootools核心的一部分,或者在mootools中 - 在以前的版本中更多。

玩得开心!