点击表格tr后获取下方tr内td及jQuery变量不可用问题排查
先来说说你遇到的几个关键点:
1. 为什么statusRow和detPane在调试器里显示(unavailable)?
这不是jQuery或选择器的问题,而是浏览器调试工具的特性。当你在事件处理函数里调试时,这两个变量属于闭包作用域,有时候调试器会因为垃圾回收机制或者异步上下文的原因,标记它们为(unavailable),但实际上代码里它们是有效的——你自己也验证了statusRow.closest('tr').next('tr')能正确找到目标行,就说明选择器逻辑是没问题的。
2. 代码里的实际bug(会导致Ajax请求永远不触发)
你这里有一个容易忽略的语法错误:判断td内容为空的时候,用了detPane.find('td').text == '',但text是jQuery的方法,不是属性,正确的写法应该是detPane.find('td').text() == ''。
因为detPane.find('td').text返回的是函数本身的引用,永远不会等于空字符串,所以你的if条件永远不成立,postDetails永远不会被调用。
3. 可以优化的选择器写法
statusRow已经是一个jQuery对象了,你不需要再用$(statusRow[0])去重新包装它。而且statusRow本身就是当前点击的tr.status-row,直接用statusRow.next('tr')就能找到对应的detail-row,不需要多此一举调用closest('tr')——毕竟this已经是<tr>元素了。
优化后的事件处理代码大概是这样:
$('table').on('click', 'tr.status-row', function() { var statusRow = $(this); // 直接用next()找到下一行,更简洁 var detPane = statusRow.next('tr'); // 先隐藏所有展开的详情行 $('.detail-view').removeClass('detail-view').addClass('hidden-detail'); // 切换当前行的显示状态 detPane.toggleClass('detail-view hidden-detail'); // 用text()方法,同时加trim避免空白字符干扰 if ($.trim(detPane.find('td').text()) === '') { var value = statusRow.find('td:first-child').text(); postDetails(value, username, sesstoken, detPane.find('td')); } });
4. 关于事件绑定的小建议
你把$(document).ready()放在了makeOrderTable函数内部,这其实没必要。如果makeOrderTable是在DOM加载完成后才被调用的,那么里面的$(document).ready()会立即执行,但这样的写法容易造成逻辑混乱。更合理的做法是把事件绑定放在全局的$(document).ready()里,或者确保makeOrderTable执行时DOM已经就绪,直接绑定事件即可。
总结一下:调试器里的(unavailable)只是显示问题,不是代码错误;真正的问题是text方法的调用错误,导致Ajax请求不触发,同时可以优化选择器和事件绑定的写法让代码更简洁健壮。
内容的提问来源于stack exchange,提问作者cryophoenix

