You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用jQuery .on()绑定事件重复触发及.off()失效问题咨询

事件绑定重复触发与off()失效问题解决

问题场景

当前代码中,每次调用showOrders()重新渲染DataTable后,都会执行showOrdersInModal()、changeStatus()、addUrl()三个函数绑定事件,导致事件触发次数随渲染次数递增;但如果在.on()前添加.off(),又会出现只有最后一个函数addUrl()的事件能正常执行的情况。

原代码

function changeStatus() { 
$('#dataTable tbody').on('change', '.orderStatus', function () {..code} 
}

function showOrdersInModal() { 
    $('#dataTable tbody').on('click', '.fa-eye-btn', function (e) {...code} 
    }
        
function addUrl() { 
$('#dataTable tbody').on('click', '.addUrl', function () {..code} 
}
    
function showOrders() {
  $.ajax({
    type: 'method',
    url: 'url',
    data: { data },
    success: function (response) {
      $('#dataTable').DataTable().clear().destroy();

      let data = JSON.parse('[' + response.replace(/}{/g, '},{') + ']');
      
      $('#dataTable').DataTable( {
        autoWidth: false,
        pageLength: 25,
        lengthMenu: [[25, 50, 100, 500, -1], [25, 50, 100, 500, 'All']],
        data: data,
        columns: [
            { data: 'receipt' },
            { data: 'first_last_name' },
            { data: 'contact_no' },
            { data: 'address' },
            { data: 'email' },
            { data: 'url' },
            { data: 'status' },
        ],
      });

          showOrdersInModal();
          changeStatus();
          addUrl();
    },
  });
}

showOrders();

问题原因

  • 不加.off()时:每次渲染DataTable都会重复绑定相同事件,导致事件触发次数累加。
  • 直接加$('#dataTable tbody').off()时:会移除该元素上所有已绑定的事件,后面函数的.off()会覆盖前面绑定的事件,最终只剩最后一个函数的事件生效。

解决方案

方案1:精准解绑对应事件

修改三个绑定函数,在绑定前只解绑当前要绑定的事件(指定事件类型和选择器),不影响其他已绑定的事件:

function changeStatus() { 
  // 仅解绑.orderStatus的change事件,再重新绑定
  $('#dataTable tbody').off('change', '.orderStatus').on('change', '.orderStatus', function () {
    // ...你的业务代码
  });
}

function showOrdersInModal() { 
  // 仅解绑.fa-eye-btn的click事件,再重新绑定
  $('#dataTable tbody').off('click', '.fa-eye-btn').on('click', '.fa-eye-btn', function (e) {
    // ...你的业务代码
  });
}
    
function addUrl() { 
  // 仅解绑.addUrl的click事件,再重新绑定
  $('#dataTable tbody').off('click', '.addUrl').on('click', '.addUrl', function () {
    // ...你的业务代码
  });
}

方案2:一次性绑定事件委托(推荐)

利用事件委托特性,把事件绑定到不会被销毁的父元素(比如#dataTable)上,只绑定一次,无需每次渲染DataTable都重复绑定:

// 页面初始化时仅绑定一次事件
$(function() {
  // 绑定状态变更事件
  $('#dataTable').on('change', 'tbody .orderStatus', function () {
    // ...原changeStatus函数内的代码
  });

  // 绑定查看订单弹窗事件
  $('#dataTable').on('click', 'tbody .fa-eye-btn', function (e) {
    // ...原showOrdersInModal函数内的代码
  });

  // 绑定添加URL事件
  $('#dataTable').on('click', 'tbody .addUrl', function () {
    // ...原addUrl函数内的代码
  });
});

function showOrders() {
  $.ajax({
    type: 'method',
    url: 'url',
    data: { data },
    success: function (response) {
      $('#dataTable').DataTable().clear().destroy();

      let data = JSON.parse('[' + response.replace(/}{/g, '},{') + ']');
      
      $('#dataTable').DataTable( {
        autoWidth: false,
        pageLength: 25,
        lengthMenu: [[25, 50, 100, 500, -1], [25, 50, 100, 500, 'All']],
        data: data,
        columns: [
            { data: 'receipt' },
            { data: 'first_last_name' },
            { data: 'contact_no' },
            { data: 'address' },
            { data: 'email' },
            { data: 'url' },
            { data: 'status' },
        ],
      });

      // 此处不再需要调用三个绑定函数
    },
  });
}

showOrders();

这种方法性能最优,从根源上避免了重复绑定问题。

方案3:批量解绑后统一重新绑定

在showOrders()的success回调中,先一次性解绑所有相关事件,再调用三个绑定函数:

function showOrders() {
  $.ajax({
    type: 'method',
    url: 'url',
    data: { data },
    success: function (response) {
      // 批量解绑所有要绑定的事件
      $('#dataTable tbody')
        .off('change', '.orderStatus')
        .off('click', '.fa-eye-btn')
        .off('click', '.addUrl');

      $('#dataTable').DataTable().clear().destroy();

      let data = JSON.parse('[' + response.replace(/}{/g, '},{') + ']');
      
      $('#dataTable').DataTable( {
        autoWidth: false,
        pageLength: 25,
        lengthMenu: [[25, 50, 100, 500, -1], [25, 50, 100, 500, 'All']],
        data: data,
        columns: [
            { data: 'receipt' },
            { data: 'first_last_name' },
            { data: 'contact_no' },
            { data: 'address' },
            { data: 'email' },
            { data: 'url' },
            { data: 'status' },
        ],
      });

      showOrdersInModal();
      changeStatus();
      addUrl();
    },
  });
}

同时三个绑定函数内不需要再添加.off()。


内容的提问来源于stack exchange,提问作者Shinxx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 08:40:27