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

时间:2014-09-17 14:12:45

标签: javascript jquery twitter-bootstrap scope

在函数范围内,我正在加载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>

更新

这是一个新的小提琴,具有我当前生产代码的最小数量。

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

3 个答案:

答案 0 :(得分:2)

您需要在文档上使用事件委派,因为有动态创建的元素。同时在文档就绪中移动click事件绑定而不是函数addRowsAndListeners()

Working example

 $(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');
            }
        });

updated fiddle:

答案 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());
});