点击DataTable触发TypeError:无法读取undefined的event_id属性求助
问题分析与解决思路
问题描述
定义3个DataTable实现联动:点击第一个表格行,过滤渲染第二个表格;点击第二个表格行,过滤JSON数据渲染第三个表格。逻辑看似正常,但随机点击第一个表格后会触发报错:
caught TypeError: Cannot read properties of undefined (reading 'event_id')
核心原因
报错根源是事件重复绑定叠加:每次点击第一个表格行时,都会给第二个表格新增一次点击事件绑定,但旧的事件并未被移除。多次点击第一个表格后,第二个表格行被点击时会触发多轮回调,此时之前的table_second_DT实例已被销毁,调用table_second_DT.row(this).data()会返回undefined,进而读取event_id时报错。
解决步骤
1. 解绑旧事件再绑定新事件
每次给第二个表格绑定点击事件前,先移除之前的事件绑定,避免重复触发:
// 先解绑#second_DT上的旧点击事件,再绑定新事件 $('#second_DT tbody').off('click', 'tr').on('click', 'tr', function() { // 原事件逻辑代码... });
2. 替换全局变量为局部变量
当前代码中columns_error_list_DT等为全局变量,易引发意外覆盖。改用const/let声明为局部变量:
// 第一个表格列配置改为局部常量 const columns_error_list_DT = [{ "data": "error_message" }, { "data": "error_type" }, { "data": "nb_errors" }, { "data": "step" }, { "data": "step_at" }, { "data": "event_id_list" } ];
3. 优化表格销毁的异常判断
销毁表格前先判断表格实例是否存在,避免销毁不存在的表格报错:
// 安全销毁第二个表格 const $secondTable = $('#error_details_DT'); if ($.fn.DataTable.isDataTable($secondTable)) { $secondTable.DataTable().destroy(); } // 安全销毁第三个表格同理 const $thirdTable = $('#event_details_DT'); if ($.fn.DataTable.isDataTable($thirdTable)) { $thirdTable.DataTable().destroy(); }
4. 增加过滤数据为空的边界处理
当df_event_details_json_filtered为空时,df_event_details_json_filtered[0]为undefined,读取event_steps会报错,需提前判断:
const df_event_details_json_filtered = df_event_details_json['data'].filter(d => data['event_id'] == d['event_id']); if (df_event_details_json_filtered.length > 0) { const event_details_DT = init_datatable(df_event_details_json_filtered[0].event_steps, columns_event_details_DT, $('#event_details_DT')); } else { // 渲染空表格或提示无数据 const emptyTable = init_datatable([], columns_event_details_DT, $('#event_details_DT')); }
5. 静态事件委托优化(可选)
将第二个表格的点击事件绑定到页面初始化时就存在的静态父元素(比如document),只需绑定一次,彻底避免重复绑定问题:
// 页面初始化时绑定一次即可,无需每次点击第一个表格都绑定 $(document).on('click', '#second_DT tbody tr', function() { // 获取当前有效的第二个表格实例 const currentSecondDT = $(this).closest('#error_details_DT').DataTable(); const data = currentSecondDT.row(this).data(); if (!data) return; // 数据为空直接返回,避免后续报错 // 后续过滤渲染第三个表格的逻辑... });
内容的提问来源于stack exchange,提问作者userHG
相关产品推荐
相关产品推荐

