querySelectorAll结合数字ID失效,如何指定表格计算总计?
我用以下代码实现实时搜索并计算总计:
$('#search').keyup(function () { var x = []; var y = []; var $total = 0; var inputString = $("#search").val(); var act = document.getElementById("labdb").value; $('td:first-child').parent().show(); $('td:first-child').parent().addClass("notHide"); $('td:first-child').parent().removeClass("toHide"); $var = $('td:first-child').parent('tr:not(:icontains(' + inputString + ')):not(:contains("Total"))'); $var.hide(); $var.addClass('toHide'); $var.removeClass('notHide') for (var price of document.querySelectorAll('tr.notHide td.price')) { x.push(parseFloat(price.innerText)); } for (var cantidad of document.querySelectorAll('tr.notHide td.quantity')) { y.push(parseFloat(cantidad.innerText)); } for(var i = 0; i <= x.length-1; i++){ $total += x[i] * y[i]; } document.getElementById("total"+act).innerText = $total.toFixed(2); });
我有多个ID为0、1的表格,通过折叠控件切换显示。现在的问题是计算总计时,会把所有带notHide类的行都算进去,多表格时结果混乱。
我尝试过几种方法但都失败:
- 直接通过选中元素调用
querySelectorAll:
var act = document.getElementById("labdb").value; var actHTML = document.getElementById("labdb"); for (var price of actHTML.document.querySelectorAll('tr.notHide td.price')) { x.push(parseFloat(price.innerText)); }
- 拼接ID选择器:
for (var price of document.querySelectorAll('#'+act+' tr.notHide td.price')) { x.push(parseFloat(price.innerText)); }
- 先获取表格再查找元素:
let myTable = document.querySelector("#"+act); let all = myTable.querySelectorAll('tr.notHide td.price'); for (var price of all) { x.push(parseFloat(price.innerText)); } for (var cantidad of all) { y.push(parseFloat(cantidad.innerText)); }
但出现控制台错误:
scripts.js:57 Uncaught DOMException: Failed to execute 'querySelector' on 'Document': '#0' is not a valid selector.
at changePrice (https://neutrino.ugr.es/js/scripts.js:57:28)
at HTMLSelectElement.(https://neutrino.ugr.es/js/scripts.js:15:5)
at HTMLSelectElement.dispatch (https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js:2:43336)
at y.handle (https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js:2:41320)
我需要让document.querySelectorAll('tr.notHide td.quantity')只获取当前选中表格内的元素,其余功能保持正常。
问题原因
CSS选择器规范中,以数字开头的ID不能直接用#0这种写法,会导致querySelector解析报错。另外原代码的搜索过滤逻辑是全局操作所有表格的行,会误修改其他表格的行状态,也是总计混乱的原因之一。
修正后的代码
$('#search').keyup(function () { var x = []; var y = []; var $total = 0; var inputString = $("#search").val(); var act = document.getElementById("labdb").value; // 用属性选择器获取当前表格,避开数字ID的选择器兼容问题 var $currentTable = $('table[id="' + act + '"]'); // 仅重置当前表格内的行状态 $currentTable.find('td:first-child').parent().show().addClass("notHide").removeClass("toHide"); // 仅过滤当前表格内不符合搜索条件的行 var $hiddenRows = $currentTable.find('td:first-child').parent('tr:not(:icontains(' + inputString + ')):not(:contains("Total"))'); $hiddenRows.hide().addClass('toHide').removeClass('notHide'); // 仅读取当前表格内目标行的数值 $currentTable.find('tr.notHide td.price').each(function() { x.push(parseFloat($(this).text())); }); $currentTable.find('tr.notHide td.quantity').each(function() { y.push(parseFloat($(this).text())); }); // 计算并更新总计 for(var i = 0; i < x.length; i++){ $total += x[i] * y[i]; } $("#total" + act).text($total.toFixed(2)); });
关键修正点
- 用
$('table[id="' + act + '"]')替代原生querySelector,解决数字ID的选择器兼容问题 - 所有行操作(显示/隐藏、类切换)都通过
find限定在当前选中表格内,避免影响其他表格 - 用jQuery的
each方法遍历元素,保持代码风格一致,同时简化逻辑
内容的提问来源于stack exchange,提问作者Sourc3w

