当用户点击 $(document).ready(function(){
$('body').on('click', 'tr', function(){
var tridx = $(this).data('track-id');
$('td div#play'+tridx).click();
});
});
标记对象时,我正在尝试触发一个按钮(在我的一个表格中),如下所示:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="sortable">
<thead>
<tr>
<th data-sort="nope">id</th>
<th data-sort="name">Artist</th>
<th data-sort="name">Title</th>
<th data-sort="name">Genre</th>
<th data-sort="duration">Duration</th>
<th data-sort="date">Release</th>
</tr>
</thead>
<tbody>
<tr data-track-id="252">
<td>
<div data-track-name="1" data-track-id="252" id="play252" class="playbtn252" style="display: none;"></div>
<div id="countlist252" data-count-list="1" style="display: block;">1</div>
</td>
<td>Simon Deoro</td>
<td>1</td>
<td>1</td>
<td>3:47</td>
<td>2016-12-06</td>
</tr>
<!-- more tr -->
</tbody>
</table>
tridx
post_index
是正确的,但我从控制台收到此错误:
未捕获RangeError:超出最大调用堆栈大小
我的代码出了什么问题,我无法理解它似乎对我来说一切正确吗?
答案 0 :(得分:3)
问题是你的函数调用(处理click
事件)是递归的。
jQuery的.on(...)
正在捕获指定选择器的点击事件(在您的情况下为tr
)及其下的所有内容。因此,click
内的按钮的tr
事件也会触发您定义的匿名函数。
在您的方案中,这是不可取,因为用户的点击会触发另一个click
事件,触发另一个click
事件,依此类推。
从函数内部对函数的每次调用都会在调用堆栈上生成一个新条目,该条目最终会变得太大并且会崩溃。 (这就是你所看到的症状。)只有当函数实际返回时,堆栈才会缩减...(这种情况永远不会发生在你身上)。
有多种方法可以避免此问题。可能最简单:忘记按钮本身有一个点击处理程序(因为按钮的点击会触发包含tr
点击事件。
或者你可以告诉jQuery停止在DOM树上应用click事件......
引用有关此主题的jQuery文档:
默认情况下,大多数事件从原始事件目标冒出来 文件要素。
在整个过程中的每个元素,jQuery调用任何元素 匹配已附加的事件处理程序。处理程序可以阻止 从文档树中进一步冒泡的事件(从而防止 通过调用来运行这些元素的处理程序
event.stopPropagation()
。当前附加的任何其他处理程序 然而,元素会运行。
为防止这种情况,请致电
event.stopImmediatePropagation()
。 (事件处理程序绑定到一个元素 按照它们被绑定的顺序被调用。)
在半相关的说明中,我强烈建议以一种使事件处理程序与私有方法与公共方法的分离尽可能清晰的方式构建jQuery代码。有关如何做的各种“建议”(我当然不能说标准!) - 我个人最喜欢的是:https://stackoverflow.com/a/5947280/817132
使用这种方法,我为所有UI代码创建一个“命名空间”(假设它只是一个小代码库)并且有一个“设置”功能(由onReady
调用),它将所有事件处理程序连接到它们的相关选择者。这些事件处理程序尽可能少,主要是调用包含真实逻辑的私有函数。
作为个人偏好的问题,我尽可能避免使用匿名函数。我附上了对函数的引用。
在一个半半相关的说明中...如果你还没有,我会强烈建议你掌握浏览器的开发者工具。 (我个人最喜欢的是随Chrome一起提供的。)
专门研究断点,并在使用观看时逐行学习步骤(以及进出功能)。
例如:https://developers.google.com/web/tools/chrome-devtools/javascript/add-breakpoints
答案 1 :(得分:2)
正如我在评论中提到的,原因是在同一TR内的元素上递归生成click事件。
在点击播放按钮之前,只需检查点击事件是否来自播放按钮:
$(document).ready(function(){
$('body').on('click', 'tr', function(e){
var tridx = $(this).data('track-id');
var $button = $('td div#play'+tridx);
if (!$button.is(e.target))
{
$button.click();
}
});
});