首页 > 解决方案 > .trigger() jquery 函数导致 Uncaught RangeError: Maximum call stack size exceeded

问题描述

我有两个带有动态链接的 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: 在 HTMLDivElement.dispatch (jquery.js:5146) 的 Data.get (jquery.js:4069) 的 camelCase (jquery.js:3988) 的 String.replace () 超出了最大调用堆栈大小在 HTMLAnchorElement 的 Object.trigger (jquery.js:8249) 上的 HTMLDivElement.elemData.handle (jquery.js:4991)。(jquery.js:8327) 在 Function.each (jquery.js:354) 在 jQuery.fn.init.each (jquery.js:189) 在 jQuery.fn.init.trigger (jquery.js:8326)

最大调用堆栈大小超出错误 - 这表明此代码中某处存在无限循环。我不知道这里怎么可能是这种情况?

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

编辑:更多研究导致我:触发点击时超出了最大调用堆栈大小

.triggerHandler()只是不呈现任何内容,并且链接不跟随。我是否需要使用其他我不知道的操作?

编辑#2:更多细节:

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

标签: javascriptjquery

解决方案


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

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

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

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

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

  • 在您的if子句中,您使用的||意思是&&(“如果不是 X 或不是 Y”将始终为真;“如果不是 X不是 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>


推荐阅读