【问题标题】:Jquery onclick function runs multiple time increasinglyJquery onclick 函数运行多次越来越多
【发布时间】:2017-03-08 13:47:22
【问题描述】:

我有一个有趣的问题,我不知道为什么会这样。我有 dataTables 和数据是在选择更改后使用 jquery ajax 发布的。我有多重选择的onclick功能。 (它必须在单击表格时运行,它会更改行样式等。)我注意到(带调试);当我在第一次加载后单击行时,onclick 按预期工作一次。但是点击第二次加载后(更改选择)运行2次并点击第三次加载后运行3次我不明白发生了什么。所以需要一些帮助。

这是加载表格的选择更改功能;

// in doc.ready
$('#groupSelect').change(function() {
  var group = $('#groupSelect').val();

  if (!$.fn.DataTable.isDataTable('#questTable')) //this is for first load
  {
    GetQuestions(group);
  } else //this is for after first load
  {
    var table = $('#questTable').DataTable();
    table.destroy();
    table.clear().draw();
    GetQuestions(group);
  }
});

这是获取数据的GetQuestions()函数;

// out of doc ready
function GetQuestions(questGroup) {
  $.ajax({
    type: 'POST',
    dataType: 'json',
    contentType: 'application/json',
    url: 'SetAudit.aspx/Questions',
    data: '{"q_group":"' + questGroup + '"}',
    success: function(result) {
      $('#questTable').DataTable({
        data: result.d,
        columns: [{
          data: 'q_id'
        }, {
          data: 'q_text'
        }]
      });


      //this click function runs multiple time at 1 click
      $('#questTable tbody').on('click', 'tr', function() {
        var table = $('#questTable').DataTable();
        var count = table.rows('.selected').count();
        $(this).toggleClass('selected');
        $('#selectedCount').text('' + table.rows('.selected').count() + '');
      });
    }
  });
}

如果我在 ajax 成功函数中创建它是可以的,但它在其他任何地方都不起作用。提前致谢。

【问题讨论】:

    标签: javascript jquery ajax datatables onclick


    【解决方案1】:

    问题是因为每次在 #groupSelect 上发生 change 事件时,您都会触发 AJAX 请求,并在该 AJAX 请求的 success 处理程序中附加 另一个 click 事件处理程序到表的tr。因此它们重复。

    要解决这个问题,我建议您将tr 事件处理程序移到success 处理程序之外,并且只在加载DOM 时运行一次。试试这个:

    function GetQuestions(questGroup) {
        $.ajax({
            type: 'POST',
            dataType: 'json',
            contentType: 'application/json',
            url: 'SetAudit.aspx/Questions',
            data: { q_group: questGroup },
            success: function (result) {
                $('#questTable').DataTable({
                    data: result.d,
                    columns: [
                        { data: 'q_id' },
                        { data: 'q_text' }
                    ]
                });
            }
        });
    }
    
    // do this on load *only*
    $('#questTable tbody').on('click', 'tr', function () {
        var table = $('#questTable').DataTable();
        var count = table.rows('.selected').count();
        $(this).toggleClass('selected');
        $('#selectedCount').text(table.rows('.selected').count());
    });
    

    【讨论】:

    • 是的,先生,我一开始并不喜欢在 ajax 成功中使用此功能。但是当我在外面创建它时(就像你的答案)它不会运行。我认为我真正的问题是。此 onclick 在其他任何地方都不起作用。我能做什么?
    • 更改事件处理程序签名:stackoverflow.com/questions/203198/…
    • 听起来 #questTable tbody 在加载时可能不在 DOM 中。尝试将其更改为$(document).on(...
    • @RoryMcCrossan 是的,你是对的。我用 $(document).on() 结构解决了它。另外stackoverflow.com/questions/8110934/…这篇文章确实非常有用。你让我明白了真正的问题。 --抱歉回复晚了--感谢您的帮助和时间。
    【解决方案2】:

    这应该可以工作

     //this click function runs multiple time at 1 click
    $('#questTable tbody').off().on('click', 'tr', function() {
      var table = $('#questTable').DataTable();
      var count = table.rows('.selected').count();
      $(this).toggleClass('selected');
      $('#selectedCount').text('' + table.rows('.selected').count() + '');
    });
    

    有多种方法可以解决问题。

    删除和添加表格 DOM 元素:这取决于您构建数据表格的方式。如果您仅从 JS 构建数据表,那么您可以采用这种方法。

    // in doc.ready
    $('#groupSelect').change(function() {
      var group = $('#groupSelect').val();
    
      if (!$.fn.DataTable.isDataTable('#questTable')) {// this is for first load
        GetQuestions(group);
      } else {//this is for after first load
        var table = $('#questTable').DataTable();
        table.destroy();
        table.clear().draw();
        // empty the table which will eventually clear all the event handlers
        $('#questTable').empty();
        GetQuestions(group);
      }
    });
    

    结合使用datatable的drawCallback事件和jQueryoff:可以在drawCallback中放置行高亮功能

    //out of doc ready
    function GetQuestions(questGroup) {
      $.ajax({
        type: 'POST',
        dataType: 'json',
        contentType: 'application/json',
        url: 'SetAudit.aspx/Questions',
        data: '{"q_group":"' + questGroup + '"}',
        success: function(result) {
          $('#questTable').DataTable({
            data: result.d,
            columns: [{
              data: 'q_id'
            }, {
              data: 'q_text'
            }],
            drawCallback: function(settings) {
              //this click function runs multiple time at 1 click
              $('#questTable tbody').off().on('click', 'tr', function() {
                var table = $('#questTable').DataTable();
                var count = table.rows('.selected').count();
                $(this).toggleClass('selected');
                $('#selectedCount').text('' + table.rows('.selected').count() + '');
              });
            }
          });
        }
      });
    }
    

    【讨论】:

    • 我一直在尝试使用您给出答案的第二部分。我不能像那样触发 onclick,但现在;我明白了为什么,我已经用 McCrossan 的建议解决了这个问题。感谢您提供这个有用而详细的答案。
    【解决方案3】:

    您将绑定添加到.change() 函数中的click 事件。这样您每次都添加一个新绑定,因此对函数的调用次数会增加。

    这样做的正确方法是将$('#questTable tbody').on('click', 'tr', function () { 移出GetQuestions

    【讨论】:

    • 是的,你是对的。我实际上尝试过,但除了 ajax 调用之外,我无法在其他任何地方触发 onclick,但现在我明白了为什么我不能并用 McCrossan 的建议解决了。谢谢你的回答。
    【解决方案4】:

    每次调用$('selector').on('click', ...) 时,您都在注册一个新回调,以便在单击与您的选择器匹配的元素时执行。所以在这种情况下,每次 ajax 调用完成时,您都会注册 另一个 点击处理程序。因此,如果您的 ajax 调用执行了 3 次,您将注册三个相同的点击处理程序,并且它们都会执行。

    您应该确保您的$('#questTable tbody').on('click', 'tr', ...) 只执行一次。

    【讨论】:

    • 是的,你是对的。除了 ajax 调用之外,我无法在其他任何地方触发 onclick,但现在我明白了为什么我不能并通过 McCrossan 的建议解决了。谢谢你的回答。
    【解决方案5】:

    您在每个 ajax 请求后添加了新的事件监听器, 从 ajax 回调中移动点击事件

    //out of doc ready
    function GetQuestions(questGroup) {
    	$.ajax({
    		type:'POST',
    		dataType:'json',
    		contentType:'application/json',
    		url:'SetAudit.aspx/Questions',
    		data: '{"q_group":"' + questGroup + '"}',
    		success: function (result) {
    			$('#questTable').DataTable({
    				data: result.d,
    				columns: [
    					{ data: 'q_id' },
    					{ data: 'q_text' }
    				]
    			});
    
    
    		}
    	});
    }
    
    //this click function runs multiple time at 1 click
    $('#questTable tbody').on('click', 'tr', function () {
    	var table = $('#questTable').DataTable();
    	var count = table.rows('.selected').count();
    	$(this).toggleClass('selected');
    	$('#selectedCount').text('' + table.rows('.selected').count() + '');
    });

    【讨论】:

    • 我实际上尝试过这个,但现在我遇到了真正的问题,并在 McCrossan 的建议下解决了它。不过谢谢你的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-29
    • 2017-01-15
    • 2010-11-01
    • 2018-05-16
    • 1970-01-01
    相关资源
    最近更新 更多