【问题标题】:JQuery event handlers firing before event occursJQuery 事件处理程序在事件发生之前触发
【发布时间】:2013-12-03 16:47:10
【问题描述】:

我正在尝试使用 for 循环将事件处理程序添加到一系列 div。应该发生的事情是,当我单击一个# containsThumbs div 时,应该显示其对应的#content div。起初,我遇到了这样一个问题,即在 for 循环中分配事件处理程序意味着无论我单击哪个 # containsThumbs div,都只会出现最后一个 #content div。

我通过调用外部函数而不是在事件处理程序本身中定义一个函数来解决此问题,但现在由于某种原因,每个# containsThumbs div 上的所有事件处理程序都会在页面加载后立即触发。之后,单击 div 将无济于事。

这是我的 HTML:

<div id="containingThumbs">
<div><img src="1.png"></div>
<div><img src="2.png"></div>
<div><img src="3.png"></div>
<div><img src="4.png"></div>
<div><img src="5.png"></div>
<div><img src="6.png"></div>
<div><img src="7.png"></div>
<div><img src="8.png"></div>
<div><img src="9.png"></div>
<div><img src="10.png"></div>
<div><img src="11.png"></div>
<div><img src="3.png"></div>
<div><img src="4.png"></div>
<div><img src="5.png"></div>
<div><img src="6.png"></div>
<div><img src="7.png"></div>
<div><img src="8.png"></div>
</div>

<div id="content">
<div><img src="1.png"></div>
<div><img src="2.png"></div>
<div><img src="3.png"></div>
<div><img src="4.png"></div>
<div><img src="5.png"></div>
<div><img src="6.png"></div>
<div><img src="7.png"></div>
<div><img src="8.png"></div>
<div><img src="9.png"></div>
<div><img src="10.png"></div>
<div><img src="11.png"></div>
<div><img src="3.png"></div>
<div><img src="4.png"></div>
<div><img src="5.png"></div>
<div><img src="6.png"></div>
<div><img src="7.png"></div>
<div><img src="8.png"></div>
</div>

这里是相关的 JS/JQuery 代码:

function expandDiv(j){
    //first hide all content that is currently displayed, if any
    $("#content div").css("display","none");
    //then display only the right content div
    $("#content div:nth-child("+j+")").css("display","inherit"); 
}

function makeInteractive(){
    for (var i = 0;i<$("#containingThumbs").children().length;i++){
        $("#containingThumbs").on("click","div",expandDiv(i));
    }
}

【问题讨论】:

    标签: javascript jquery event-handling


    【解决方案1】:

    这一行:

    $("#containingThumbs").on("click","div",expandDiv(i));
    

    调用 expandDiv 并将其返回值传递给on,与foo(bar()) 完全相同调用 bar 并将结果传递给foo。你传入on 的应该是函数引用。

    纠正该代码的几种方法:

    1. 如果你只是想要i,因为你想知道点击了哪个div,你不需要它;在对expandTab 的调用中,this 将引用 div 的 DOM 元素。因此,如果您将expandTab 更改为使用this,则只需删除expandTab 之后的(i)

      function makeInteractive(){
          for (var i = 0;i<$("#containingThumbs").children().length;i++){
              $("#containingThumbs").on("click","div",expandTab);
              // No (i) ---------------------------------------^
          }
      }
      

      同样,您必须将 expandTab 更改为使用 this 作为 div。

    2. 您可以使用闭包传递i

      function makeInteractive(){
          for (var i = 0;i<$("#containingThumbs").children().length;i++){
              $("#containingThumbs").on("click","div",makeHandler(i));
          }
          function makeHandler(index) {
              return expandDiv(index);
          }
      }
      

      假设expandTab 期望将该索引作为其第一个参数,并且不使用事件对象。

    3. 或者如果你想稍微改变expandDiv,你可以通过让jQuery将额外的参数传递给event data来处理它:

      function makeInteractive(){
          for (var i = 0;i<$("#containingThumbs").children().length;i++){
              $("#containingThumbs").on("click", "div", i, expandDiv);
              // Note the `i` --------------------------^           ^--- no ()
          }
      }
      

      expandDiv 将使用event.data 作为索引。

    【讨论】:

    • 我现在正在尝试方法1,所以我的代码行是 $("# containsThumbs").on("click","div",expandDiv);但现在我收到“未捕获的错误:语法错误,无法识别的表达式::nth-​​child”错误消息,因为函数输入是一个事件,但我需要一个索引值来知道要显示哪个#content div。
    • ...也尝试方法 2 给我一个“未捕获的类型错误:对象 div 没有方法 'apply'”我不明白的错误。方法 3...似乎会以与页面首次加载时相同的方式触发所有事件,但没有可见效果。
    • @user3060388:再次,请参阅上面的注释。您说您尝试了方法 1,但您谈到了使用索引,我已经明确告诉您,使用方法 1 您必须改用 this。您已经使用方法 2,但使用了事件对象,我已经明确表示“假设 expandTab 期望将该索引视为其第一个参数,并且不使用事件对象。”再次使用方法 3,正如我所说,您将使用 event.data 作为索引。
    • 啊,明白了!非常感谢,起初我不太明白你的意思,但使用方法 1 并将 expandDiv 中的 i 替换为 $(this).index()+1 就可以了!它现在运行良好。
    猜你喜欢
    • 2013-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多