简体   繁体   English

jQuery点击工作一次,而不是两次

[英]jQuery Click Working Once, not Twice

In the scope of a function, I am loading HTML to display in a Bootstrap modal via AJAX. 在函数的范围内,我正在加载HTML以通过AJAX在Bootstrap模式中显示。 The AJAX load is expensive, and I want to cache the content that it loads. AJAX负载很昂贵,我想缓存它加载的内容。 However, the rows of a table in the HTML can change dynamically, and need click listeners bound to them. 但是,HTML中的表行可以动态更改,并且需要单击绑定到它们的侦听器。

I don't know how best to explain the situation other than posting some code. 除了发布一些代码之外,我不知道如何最好地解释这种情况。

Fiddle: http://jsfiddle.net/vvc1j1eh/1/ 小提琴: http//jsfiddle.net/vvc1j1eh/1/

So the big question would be, why does the first load click work the first time, but not after I try to re-use the cached content? 所以最大的问题是,为什么第一次加载点击工作是第一次,但是在我尝试重新使用缓存内容之后呢? Also why does the second load in scope click work every time? 另外,为什么每次点击范围内的第二次加载都会起作用?

Edit: Better Explanation of the Problem 编辑:更好地解释问题

Load the page, and click "Load" to show the dialog. 加载页面,然后单击“加载”以显示对话框。 If you click on a row, an alert will pop up with the row you clicked on. 如果单击某一行,将弹出一个警告,其中包含您单击的行。 Click anywhere outside of the dialog to hide it, and click "Load" again. 单击对话框外的任意位置以隐藏它,然后再次单击“加载”。 This time, when you click rows the alert message won't pop up. 这次,当您单击行时,不会弹出警报消息。

If you do the exact same process for the Load With Right Scope button, you will still get alerts when clicking on rows the second time the dialog is displayed. 如果对“使用右侧范围加载”按钮执行完全相同的过程,则在第二次显示对话框时单击行时仍会收到警报。

Delegation: 代表团:

It's hard to explain in an example, but the content "document" page is also loaded dynamically by AJAX along with multiple pages. 在一个例子中很难解释,但内容“文档”页面也是由AJAX和多个页面动态加载的。 These multiple pages are shown and hidden as the user navigates the webapp, so I can't just bind a global listener to the document. 当用户导航webapp时,会显示和隐藏这些多个页面,因此我不能将全局侦听器绑定到文档。

This would be the closest equivalent of what I was doing when trying delegation: 这将是我在尝试授权时所做的最接近的事情:

var $data = expensiveAjaxLoad();
$data.on('click', 'tbody td', function() {
    alert($(this).html());
});
$('#load').click(function() {
    addRowsAndListeners($data);

    $('#content').html($data);
    $('#modal').modal('show');
});

It still doesn't answer the big question , which is why do the events not bind the second time? 它仍然没有回答大问题 ,这就是为什么这些事件第二次没有约束? They bind the first time, and as I'm debugging, there doesn't seem to be any change to the scope variable $data . 它们第一次绑定,并且在我调试时,范围变量$data似乎没有任何变化。

StackSnippet: 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> 

Update: 更新:

Here is a new Fiddle with the minimum amount of my current production code. 这是一个新的小提琴,具有我当前生产代码的最小数量。

http://jsfiddle.net/0vb2psv4/1/ http://jsfiddle.net/0vb2psv4/1/

You need to use event delegation on document, as there are dynamicaly created elements. 您需要在文档上使用事件委派,因为有动态创建的元素。 Also move the click event binding in document ready instead of function addRowsAndListeners() 同时在文档就绪中移动click事件绑定而不是函数addRowsAndListeners()

Working example 工作实例

 $(document).on('click','tbody td',function() {
        alert($(this).html());
    });

UPDATE: With your original code, delegate it on content (container of table or model body) as your table is also dynamic 更新:使用原始代码,将其委托给内容(表格或模型主体的容器),因为您的表格也是动态的

$("#content").on('click', 'tbody tr', function(e) {
        e.preventDefault();
            var $this = $(this);
            if ($this.hasClass('selectable')) {
                $this.toggleClass('success');
            }
        });

updated fiddle: 更新小提琴:

I was able to achieve your desired functionality by altering your $('#load').click() : JSFiddle DEMO 我能够通过改变你的$('#load').click()来实现你想要的功能.Click $('#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
    });
});

Because you're adding rows jQuery is not aware of them. 因为你正在添加行jQuery不知道它们。 You need to delegate the click event - 您需要委派点击事件 -

$(document).on('click', 'tbody td', function() {
    alert($(this).html());
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM