0

我在将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]);
          };


        }
      }

  }
})();
4

2 回答 2

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
}
于 2013-11-14T15:37:04.953 回答
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;


          }
      }

   }
})();

...是的,该功能可以内联,我只是将其分解为更清楚。

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

于 2013-11-14T16:21:57.807 回答