在函数范围内,我正在加载HTML以通过AJAX在Bootstrap模式中显示。 AJAX负载很昂贵,我想缓存它加载的内容。但是,HTML中表的行可以动态更改,并且需要单击绑定到它们的侦听器。
除了发布一些代码之外,我不知道如何最好地解释这种情况。
小提琴:http://jsfiddle.net/vvc1j1eh/1/
所以最大的问题是,为什么第一次加载点击工作是第一次,但是在我尝试重新使用缓存内容之后呢?另外,为什么每次点击范围内的第二次加载都会起作用?
编辑:更好地解释问题
加载页面,然后单击“加载”以显示对话框。如果单击某一行,将弹出一个警告,其中包含您单击的行。单击对话框外的任意位置以隐藏它,然后再次单击“加载”。这次,当您单击行时,不会弹出警告消息。
如果对“使用右侧范围加载”按钮执行完全相同的过程,则在第二次显示对话框时单击行时仍会收到警报。
团:
在一个例子中很难解释,但内容“文档”页面也是由AJAX和多个页面动态加载的。当用户导航webapp时,会显示和隐藏这些多个页面,因此我不能将全局侦听器绑定到文档。
这将是我在尝试授权时所做的最接近的事情:
var $data = expensiveAjaxLoad();
$data.on('click', 'tbody td', function() {
alert($(this).html());
});
$('#load').click(function() {
addRowsAndListeners($data);
$('#content').html($data);
$('#modal').modal('show');
});
它仍然没有回答大问题,这就是为什么事件不会第二次绑定?它们是第一次绑定,在我调试时,范围变量$data
似乎没有任何变化。
StackSnippet:
$(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>
更新
这是一个新的小提琴,具有我当前生产代码的最小数量。
答案 0 :(得分:2)
您需要在文档上使用事件委派,因为有动态创建的元素。同时在文档就绪中移动click事件绑定而不是函数addRowsAndListeners()
$(document).on('click','tbody td',function() {
alert($(this).html());
});
更新:使用原始代码,将其委托给内容(表格或模型正文的容器),因为您的表格也是动态的
$("#content").on('click', 'tbody tr', function(e) {
e.preventDefault();
var $this = $(this);
if ($this.hasClass('selectable')) {
$this.toggleClass('success');
}
});
答案 1 :(得分:1)
通过更改$('#load').click()
:JSFiddle DEMO
$('#load').on("click", function() { //changed to on("click")
addRowsAndListeners($data);
$('#content').html($data);
$('#modal').modal('show');
//remove the on("click") and set up a new on("click") to just show the modal
$('#load').off("click").on("click", function() {
$('#modal').modal('show');
//you could add additional logic in here if you need to conditionally redo the ajax call
});
});
答案 2 :(得分:0)
因为你正在添加行,所以jQuery并不知道它们。您需要委派click事件 -
$(document).on('click', 'tbody td', function() {
alert($(this).html());
});