【问题标题】:.trigger() jquery function is causing Uncaught RangeError: Maximum call stack size exceeded.trigger() jquery 函数导致 Uncaught RangeError: Maximum call stack size exceeded
【发布时间】:2018-08-15 13:40:59
【问题描述】:

我有两个带有动态链接的 div,它们有时会被填充,有时不会。如果您单击如下所示的链接:

<a href="#">

什么都没有发生,我阻止了默认操作,但是如果链接是:

<a href="/path/to/a/page">

它会随之而来。

我希望能够点击周围的 div,并使用与上述相同的逻辑。所以如果我点击红色并且有一个有效的链接,链接就会跟随。我正在使用trigger() 来尝试这个。

情况如下:

$(function() {
	$(".container").click(function(e) {
    var clickTarget = $(e.target).attr("href");
    var clickTargetLink = $(this).find(".container-link");
      if ((clickTarget != "#") || (clickTarget != undefined)) {
        clickTargetLink.trigger("click");
      } else {
        e.preventDefault();
      }
  });
});
.container {
  padding: 50px;
  margin-bottom: 1rem;
  background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <a class="container-link" href="google.com">link</a>
</div>
<div class="container">
  <a class="container-link" href="#">link</a>
</div>

最终发生的事情是点击链接中带有 google.com 的红色 div:

jquery.js:3988 Uncaught RangeError: 超出最大调用堆栈大小 在 String.replace() 在camelCase (jquery.js:3988) 在 Data.get (jquery.js:4069) 在 HTMLDivElement.dispatch (jquery.js:5146) 在 HTMLDivElement.elemData.handle (jquery.js:4991) 在 Object.trigger (jquery.js:8249) 在 HTMLAnchorElement。 (jquery.js:8327) 在 Function.each (jquery.js:354) 在 jQuery.fn.init.each (jquery.js:189) 在 jQuery.fn.init.trigger (jquery.js:8326)

Maximum call stack size exceeded error - 这表明此代码中某处存在无限循环。我不知道这里怎么可能是这种情况?

为什么这段代码会导致最大调用堆栈大小错误?

编辑:更多研究使我发现:Maximum call stack size exceeded on trigger click

.triggerHandler() 什么都不渲染,链接也没有跟随。我是否需要使用其他我不知道的操作?

编辑#2:更多细节:

  1. 我无法更改/添加标记结构。
  2. 红色的 div 必须是完全可点击的,因为当链接为空时,还有一个与之相关的操作:&lt;a href="#"&gt;
  3. 我尝试了e.stopPropagation(); - 解决了错误,但链接没有跟随
  4. 我试过triggerHandler() - http://api.jquery.com/triggerhandler/

【问题讨论】:

  • 你的点击处理器触发了点击事件,由点击处理器处理,点击处理器触发点击事件,...
  • 检查浏览器控制台,它显示too much recursion(在 Firefox 中)。您正在递归触发点击事件

标签: javascript jquery


【解决方案1】:

您可以选择检查是否是链接或被点击的容器。如果是链接,请不要触发再次点击。

$(function() {
  $(".container").click(function(e) {
    var $containerLink = $(this).find('.container-link');
    //check to see if the container was clicked, or if the link was clicked
    var linkWasClicked = $(e.target).is('.container-link');
    
    if (['#', undefined].indexOf($containerLink.attr('href')) > -1) {
      e.preventDefault();
    } else if (!linkWasClicked) { //only trigger the link if it was not clicked
      $containerLink[0].click();
    }
  });
});
.container {
  padding: 50px;
  margin-bottom: 1rem;
  background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <a class="container-link" href="https://google.com">link</a>
</div>
<div class="container">
  <a class="container-link" href="#">link</a>
</div>

【讨论】:

    【解决方案2】:

    您的点击处理程序正在触发一个新的点击事件,该事件由点击处理程序处理,该事件触发一个新的点击事件,该事件由点击处理程序处理,最终...最终溢出堆栈。

    在 cmets 中(现在在更新的问题中)您已经阐明了此代码的目的:

    红色区域必须是可点击的,而不仅仅是链接。这就是为什么我尝试使用 .trigger() 以便在单击 div 时触发 div 内的子链接的单击。

    除了修复无限循环之外,这还需要进行一些更改:

    • 您现有的代码在事件目标本身上寻找href,这将不允许红色区域可点击(因为事件目标不一定是具有 href 属性的元素)。我已将其更改为忽略事件目标(这并不是您真正关心的),而是从容器元素内的链接中提取 href。

    • 在您的 if 子句中,当您的意思是 &amp;&amp; 时,您使用了 ||(“如果它不是 X 或它不是 Y”将始终为真;“如果它不是 X 并且 em> 这不是 Y”是你的意思。)

    这里通过直接设置窗口位置来解决无限递归,而不是触发另一个点击事件。

    $(function() {
      $(".container").click(function(e) {
        var clickTarget = $(this).find("a.container-link").attr("href");
        if (clickTarget && clickTarget !== "#") {
          window.location=clickTarget;
        } else {
          // prevent link navigation from occurring
          console.log("Blocking click");
          e.preventDefault();
        }
      });
    });
    .container {
      padding: 10px;
      margin-bottom: 1rem;
      background-color: red;
      cursor: pointer
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="container">
      <a class="container-link" href="https://example.com">Normal link</a>
    </div>
    <div class="container">
      <a class="container-link" href="#">Blocked link</a>
    </div>

    【讨论】:

    • 红色区域需要可点击,而不仅仅是链接。对不起。
    • 这就是我尝试使用.trigger() 的原因,以便在单击 div 时触发对 div 内的子链接的单击。
    • 啊,我明白了。好的,请稍等,我会编辑答案
    • 如果所有红色区域和链接都应该是可点击的并且它们执行相同的重定向,为什么不将整个红色区域设置为&lt;a&gt; 持有带有“链接”一词的&lt;span&gt;?这样,无论你在哪里点击红色区域,它都会重定向
    • @CalvinNunes 我正在尝试实现的特定项目中的标记无法更改。
    【解决方案3】:

    当容器被点击时,你触发点击它里面的链接传播回容器,再次点击链接,等等。您一遍又一遍地递归单击链接,这导致了错误。在容器的click 事件处理程序中,您需要检查事件的 currentTarget 是否等于事件的目标以单击链接(防止递归)。要触发点击链接以重定向到另一个页面,您需要像这样获取要点击的实际 DOM 元素(不是 jQuery 对象):clickTargetLink[0].click()(jQuery 总是返回一个元素数组)。

    .container {
      padding: 50px;
      margin-bottom: 1rem;
      background-color: red;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="container">
      <a class="container-link" href="http://www.example.com">link</a>
    </div>
    <div class="container">
      <a class="container-link" href="#">link</a>
    </div>
    <script>
    $(function() {
    	$(".container").click(function(e) {
        var clickTarget = $(e.target).attr("href");
        var clickTargetLink = $(this).find(".container-link");
          if (e.currentTarget==e.target) {
            clickTargetLink[0].click();
          } else {
           if(clickTarget!==undefined&&clickTarget == "#"){
           e.preventDefault();
           }
          }
      });
    });
    </script>

    【讨论】:

      【解决方案4】:

      因为.container-link.container 内部,所以.container-link 的点击事件也会触发.container 的点击,除非您执行stopPrpogation(),否则会导致无限循环。

      if 中使用stopPropagation()(在触发click 之后)。

      【讨论】:

      • 即使在触发事件后使用stopPropagation(),我仍然看到Maximum call stack size exceeded
      【解决方案5】:

      正如您在 cmets 中看到的那样,您正在触发处理程序中的单击,以处理导致进入循环的单击。点击->处理程序->触发点击->处理程序--->

      所以基本上将处理程序附加到链接本身,或者如果您想将其附加到父级,只需检查目标是否为链接

      您还可以查看此主题以了解有关主题 In jQuery, how can I tell between a programmatic and user click? 的更多信息

      【讨论】:

        【解决方案6】:

        用这种方式改进你的 JS:

        $(function () {
          $(".container").click(function (e) {
            var clickTarget = $(e.target).attr("href");
            var clickTargetLink = $(this).find(".container-link");
            if ((clickTarget === "#") || (clickTarget === undefined)) return false
          })
        })
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-25
          • 1970-01-01
          相关资源
          最近更新 更多