在函数范围内,我正在加载 HTML 以通过 AJAX 在 Bootstrap 模态中显示。 AJAX 加载很昂贵,我想缓存它加载的内容。但是,HTML 中表格的行是动态变化的,需要绑定(bind)点击监听器。
除了发布一些代码,我不知道如何最好地解释这种情况。
fiddle :http://jsfiddle.net/vvc1j1eh/1/
所以最大的问题是,为什么第一次加载点击第一次有效,但在我尝试重新使用缓存内容后却无效?另外,为什么第二次加载范围点击每次都有效?
编辑:更好地解释问题
加载页面,然后单击“加载”以显示对话框。如果您单击一行,将弹出一个警告,其中包含您单击的行。单击对话框外的任意位置将其隐藏,然后再次单击“加载”。这一次,当您单击行时,不会弹出警告消息。
如果您对 Load With Right Scope 按钮执行完全相同的过程,您将在第二次显示对话框时单击行时仍会收到警报。
委派:
很难在示例中解释,但是内容“文档”页面也通过 AJAX 与多个页面一起动态加载。这些多个页面在用户浏览 web 应用程序时显示和隐藏,因此我不能只将全局监听器绑定(bind)到文档。
这将是我在尝试委派时所做的最接近的等价物:
var $data = expensiveAjaxLoad();
$data.on('click', 'tbody td', function() {
alert($(this).html());
});
$('#load').click(function() {
addRowsAndListeners($data);
$('#content').html($data);
$('#modal').modal('show');
});
它仍然没有回答大问题,即为什么事件不会第二次绑定(bind)?它们是第一次绑定(bind),在我调试时,范围变量 $data
似乎没有任何变化。
堆栈代码段:
$(document).ready(function() {
//Scope of the function
//$data works the first time, but additional row
//clicks don't register events
var $data = expensiveAjaxLoad();
$('#load').click(function() {
addRowsAndListeners($data);
$('#content').html($data);
$('#modal').modal('show');
});
//Why does this work?
$('#load-scope').click(function() {
var $better = expensiveAjaxLoad();
addRowsAndListeners($better);
$('#content').html($better);
$('#modal').modal('show');
});
});
function expensiveAjaxLoad() {
var html = [];
html.push('<table><tbody>');
html.push('</tbody></table>');
return $(html.join(''));
}
function addRowsAndListeners($data) {
var html = [];
//Rows can vary, don't need to recreate the entire table
for (var i = 0; i < 5; i++) {
html.push('<tr><td>Row ');
html.push((i + 1));
html.push('</td></tr>');
}
$('tbody', $data).html(html.join(''));
//Something here is not binding correctly
$('tbody td', $data).click(function() {
alert($(this).html());
});
}
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
</head>
<body>
<div>
<h1>Hello Alice</h1>
<button id="load">Load</button>
<button id="load-scope">Load With Right Scope</button>
</div>
<div id="modal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Modal Title</h4>
</div>
<div id="content" class="modal-body">
</div>
</div>
</div>
</div>
</body>
</html>
更新:
这是一个新的 Fiddle,其中包含我当前生产代码的最少数量。
最佳答案
您需要在文档上使用事件委托(delegate),因为有动态创建的元素。也将点击事件绑定(bind)移动到 document ready 而不是函数 addRowsAndListeners()
$(document).on('click','tbody td',function() {
alert($(this).html());
});
更新:使用您的原始代码,将其委托(delegate)给内容(表格容器或模型主体),因为您的表格也是动态的
$("#content").on('click', 'tbody tr', function(e) {
e.preventDefault();
var $this = $(this);
if ($this.hasClass('selectable')) {
$this.toggleClass('success');
}
});
关于javascript - jQuery 点击工作一次,而不是两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25892990/