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

时间:2013-11-14 15:27:20

标签: javascript html onclick while-loop getelementsbytagname

我在将 onclick 附加到循环内的每个链接对象时遇到问题,当您单击该链接时,它似乎总是返回与循环中第一个项相关的数据,无论是什么被点击了。我需要点击每个链接以获得该链接的相关href

在下面的示例中,无论点击了哪个链接,console.log都会始终显示“http://example.com/link1/

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的:

(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]);
          };


        }
      }

  }
})();

2 个答案:

答案 0 :(得分:1)

问题是,当发生点击时,getTheLinks已设置为列表中的最后一个h2。要防止每个循环覆盖前一个循环,您必须使用闭包使用此模式创建新上下文:(function(i){...})(i)

正如Felix Kling所提到的,关闭实际上是问题的根源。以下文章可以启发您对此概念的启发。有一段关于你遇到的这个常见陷阱: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);
    }
})();

我不熟悉JSLint。如果你需要JSLint有效,我想你必须将这个函数定义移到循环之外,如下所示:

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

答案 1 :(得分:1)

我会继续展示我对此问题的首选解决方案

(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;


          }
      }

   }
})();

...是的,这个功能可以内联,我只是把它弄清楚了。

记住事件函数接收事件对象,并且应该(如果可能)是用于建立处理事件的上下文的唯一事物。在这种情况下,上下文是“被点击的链接”,事件回答了该问题,而不是封闭的上下文。从软件设计的角度来看,我认为使用该事件将是一个更清洁的解决方案,并且从长远来看更容易维护。