无<thead>且左侧为表头的树形表格如何按行排序?
树形表格按行排序实现方案
实现思路
- 先将所有行按父子层级分组,每个父节点下的子节点单独排序,避免跨父节点打乱树结构
- 排序时仅操作同一父级下的同级子行,无父节点的根节点单独排序
- 排序完成后按层级顺序重新把行插回表格,完整保留树形插件的所有自定义属性和绑定事件
完整实现代码
/** * 树形表格按行排序函数 * @param {Number} sortColumn 要排序的列索引,从1开始(第一列为左侧表头,数据列从1计数) * @param {Boolean} asc 是否升序,true=升序,false=降序 */ function sortTreeTable(sortColumn, asc = true) { const $table = $('table'); // 1. 存储所有行数据,方便按id查找 const allRows = {}; $table.find('tr').each(function() { const id = $(this).data('node-id'); allRows[id] = $(this).clone(true); // 克隆保留已绑定的事件 }); // 2. 构建层级关系,拆分根节点和子节点映射 const rootRows = []; const childrenMap = {}; Object.keys(allRows).forEach(id => { const pid = allRows[id].data('node-pid'); if (!pid) { rootRows.push(allRows[id]); } else { if (!childrenMap[pid]) childrenMap[pid] = []; childrenMap[pid].push(allRows[id]); } }); // 3. 通用排序逻辑,兼容数字和字符串类型的单元格内容 const sortRows = (rowsArr) => { return rowsArr.sort((a, b) => { const valA = a.find(`td:eq(${sortColumn - 1})`).text().trim(); const valB = b.find(`td:eq(${sortColumn - 1})`).text().trim(); const numA = parseFloat(valA); const numB = parseFloat(valB); if (!isNaN(numA) && !isNaN(numB)) { return asc ? numA - numB : numB - numA; } return asc ? valA.localeCompare(valB) : valB.localeCompare(valA); }); }; // 4. 递归插入排序后的行:先插入父节点,再插入对应排序后的子节点 const insertSortedRows = (rowsArr) => { rowsArr.forEach(row => { $table.append(row); const id = row.data('node-id'); if (childrenMap[id]) { const sortedChildren = sortRows(childrenMap[id]); insertSortedRows(sortedChildren); } }); }; // 5. 清空原有内容,插入排序后的行 $table.empty(); const sortedRoot = sortRows(rootRows); insertSortedRows(sortedRoot); // 若排序后树形折叠/展开功能失效,在此处重新调用树形表格的初始化方法即可 }
使用示例
要按第二列(左侧表头之后的第一列数据)升序排序,直接调用:sortTreeTable(1, true)
如需降序排序,将第二个参数改为false即可。
注意事项
如果单元格内包含特殊标签、格式化符号,可自行修改sortRows函数中的取值逻辑,适配实际业务场景。
内容的提问来源于stack exchange,提问作者Lily
相关产品推荐
相关产品推荐

