简体   繁体   English

JavaScript:将onclick附加到“while”循环内的链接

[英]JavaScript: Attach onclick to a link inside “while” loop

I'm having trouble with attaching an onclick to each link object inside a loop, when you click the link, it seems to always return data relevant to the first item in the loop, regardless what was clicked. 我在将一个onclick附加到循环内的每个链接对象时遇到问题,当您单击该链接时,它似乎总是返回与循环中第一个项相关的数据,无论点击什么。 Where as i need each link clicked to have the relevant href to that link 在哪里我需要点击每个链接以获得该链接的相关href

In the example below, regardless what link was clicked, the console.log would always show " http://example.com/link1/ " 在下面的示例中,无论单击哪个链接,console.log将始终显示“ http://example.com/link1/

HTML Example HTML示例

  <li>
    <h2><a class="t" href="http://example.com/link1/"><i>Link 1 text</i></a></h2>
    <div class="panel" >Content</div>
  </li>

  <li>
    <h2><a class="t" href="http://example.com/link2/"><i>Link 2 text</i></a></h2>
    <div class="panel" >Content</div>
  </li>

  <li>
    <h2><a class="t" href="http://example.com/link3/"><i>Link 3 text</i></a></h2>
    <div class="panel" >Content</div>
  </li>

</ul>

JavaScript: JavaScript的:

(function(){
  var theh2s = document.getElementById("panelList").getElementsByTagName("h2"), 
  i = theh2s.length;

  while (i--) {

      var getTheLinks = theh2s[i].getElementsByTagName("a");

      if (getTheLinks){
        if (getTheLinks[0].href){

          console.log(getTheLinks[0].href);

          getTheLinks[0].onclick = function() {
            console.log(getTheLinks[0].href);
            _gaq.push(['_trackEvent', 'Homepage', 'AB Click - Test B', getTheLinks[0].href]);
          };


        }
      }

  }
})();

The problem is that when a click occured, getTheLinks has already been set to the last h2 in the list. 问题是当发生点击时, getTheLinks已经被设置为列表中的最后一个h2 To prevent each loop to override the previous one, you have to use a closure create a new context using this pattern : (function(i){...})(i) . 为了防止每个循环覆盖前一个循环,你必须使用一个闭包使用这个模式创建一个新的上下文: (function(i){...})(i)

As Felix Kling mentionned, a closure actually is the source of the problem. 正如Felix Kling所提到的,关闭实际上是问题的根源。 The following article could enlighten you about this concept. 以下文章可以启发您对此概念的启发。 There is a paragraph concerning this common pitfall you just have encountered : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures . 有一段关于您刚遇到的常见陷阱: https//developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures

(function () {
    var theh2s = document.getElementById("panelList").getElementsByTagName("h2"),
        i = theh2s.length;
    while (i--) {
        (function (i) {
            var getTheLinks = theh2s[i].getElementsByTagName("a");
            if (getTheLinks) {
                if (getTheLinks[0].href) {
                    console.log(getTheLinks[0].href);
                    getTheLinks[0].onclick = function () {
                        console.log(getTheLinks[0].href);
                        _gaq.push(['_trackEvent', 'Homepage', 'AB Click - Test B', getTheLinks[0].href]);
                    };
                }
            }
        })(i);
    }
})();

I'm not familiar with JSLint. 我不熟悉JSLint。 If you need to be JSLint valid, I guess you'll have to move the function definition outside the loop like this : 如果你需要JSLint有效,我想你必须将这个函数定义移到循环之外,如下所示:

while (i--) {
    f(i)
}
function f(i) {
    // same as above
}

I'll go ahead and demonstrate my preferred solution to this problem 我将继续展示我对此问题的首选解决方案

(function(){
  function processLinkClick(e) {
    var link = e.currentTarget;
    console.log(link.href);
    _gaq.push(['_trackEvent', 'Homepage', 'AB Click - Test B', link.href]);
  }

  var theh2s = document.getElementById("panelList").getElementsByTagName("h2"), 
  i = theh2s.length;

  while (i--) {

      var getTheLinks = theh2s[i].getElementsByTagName("a");

      if (getTheLinks){
          if (getTheLinks[0].href){

              console.log(getTheLinks[0].href);

              getTheLinks[0].onclick = processLinkClick;


          }
      }

   }
})();

... and yes that function could be inlined, I just broke it out to be more clear. ......是的,这个功能可以内联,我只是把它弄清楚了。

Remember event functions receive an event object, and that should (if possible) be the only thing you use to establish context for processing the event. 记住事件函数接收事件对象,并且应该(如果可能)是用于建立处理事件的上下文的唯一事物。 In this case the context is, "link that was clicked", the event answers that question, not the enclosing context. 在这种情况下,上下文是“被点击的链接”,事件回答了该问题,而不是封闭的上下文。 I would argue from a software design point of view that using the event is going to be a cleaner solution and easier to maintain in the long run. 从软件设计的角度来看,我认为使用该事件将是一个更清洁的解决方案,从长远来看更容易维护。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM