两列可排序筛选HTML表格拆分并排显示及iframe适配需求
解决方案:拆分DataTables为双栏响应式布局
核心思路
因为DataTables是动态渲染的,我们需要在每次表格重绘(比如筛选、排序操作后)自动将行分割为左右两部分,同时保持两个表格的表头、筛选功能完全同步,再通过CSS实现响应式布局,满足小屏幕自动堆叠的需求。
步骤1:调整HTML结构与样式
把原单个表格容器改成包含两个表格的弹性布局容器,复制表头和页脚到第二个表格,用CSS实现响应式排列:
<!DOCTYPE html> <html lang="en-US"> <head> <title>Table</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.js"></script> <script type="text/javascript" src="http://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js"></script> <style> .table-container { margin: auto; width: 90%; display: flex; gap: 20px; flex-wrap: wrap; padding: 10px; } .table-wrapper { flex: 1; min-width: 300px; /* 小屏幕自动堆叠的阈值 */ border: 3px solid #73AD21; padding: 10px; } #example, #example-clone { width: 100% !important; } </style> </head> <body> <div class="table-container"> <div class="table-wrapper"> <table id="example" class="" style="width:100%"> <thead> <tr> <th style="text-align:left;width:150px">Place <i class="fa fa-sort"></i></th> <th style="text-align:left;width:150px">Date <i class="fa fa-sort"></i></th> </tr> </thead> <tbody></tbody> <tfoot> <tr> <th></th> <th></th> </tr> </tfoot> </table> </div> <div class="table-wrapper"> <table id="example-clone" class="" style="width:100%"> <thead> <tr> <th style="text-align:left;width:150px">Place <i class="fa fa-sort"></i></th> <th style="text-align:left;width:150px">Date <i class="fa fa-sort"></i></th> </tr> </thead> <tbody></tbody> <tfoot> <tr> <th></th> <th></th> </tr> </tfoot> </table> </div> </div> <script> $(document).ready(function() { // 初始化主表格 var table = $('#example').DataTable({ initComplete: function () { // 为主表格添加筛选框 this.api().columns().every( function () { var that = this; $(this.footer()).html(`<input type="text" placeholder="Search ${$(this.header()).text()}" />`); $( 'input', this.footer() ).on( 'keyup change clear', function () { if ( that.search() !== this.value ) { that.search( this.value ).draw(); } }); }); // 复制筛选框到克隆表格并同步事件 $('#example tfoot input').each(function(index) { var cloneInput = $(this).clone(); $('#example-clone tfoot th').eq(index).html(cloneInput); cloneInput.on('keyup change clear', function() { table.column(index).search($(this).val()).draw(); }); }); }, drawCallback: function(settings) { // 每次重绘后拆分可见行到左右表格 var allRows = this.api().rows({search:'applied'}).nodes(); var halfLength = Math.ceil(allRows.length / 2); var leftRows = $(allRows).slice(0, halfLength); var rightRows = $(allRows).slice(halfLength); $('#example tbody').html(leftRows); $('#example-clone tbody').html(rightRows); }, // 你的原始数据(可替换为动态数据源) data: [ ["Edinburgh","2011/04/25"],["Tokyo","2011/07/25"],["San Francisco","2009/01/12"],["Edinburgh","2012/03/29"],["Tokyo","2008/11/28"],["New York","2012/12/02"],["San Francisco","2012/08/06"],["Tokyo","2010/10/14"],["San Francisco","2009/09/15"],["Edinburgh","2008/12/13"],["London","2008/12/19"],["Edinburgh","2013/03/03"],["San Francisco","2008/10/16"],["London","2012/12/18"],["London","2010/03/17"],["London","2012/11/27"],["New York","2010/06/09"],["New York","2009/04/10"],["London","2012/10/13"],["Edinburgh","2012/09/26"],["New York","2011/09/03"],["New York","2009/06/25"],["New York","2011/12/12"],["Sydney","2010/09/20"],["London","2009/10/09"],["Edinburgh","2010/12/22"],["Singapore","2010/11/14"],["San Francisco","2011/06/07"],["San Francisco","2010/03/11"],["Tokyo","2011/08/14"],["Sydney","2011/06/02"],["London","2009/10/22"],["London","2011/05/07"],["San Francisco","2008/10/26"],["Edinburgh","2011/03/09"],["San Francisco","2009/12/09"],["San Francisco","2008/12/16"],["San Francisco","2010/02/12"],["San Francisco","2009/02/14"],["London","2008/12/11"],["New York","2008/09/26"] ] }); // 同步克隆表格的表头排序事件 $('#example-clone thead th').on('click', function() { var index = $(this).index(); var currentOrder = table.order()[0]; var newOrder = currentOrder[0] === index ? (currentOrder[1] === 'asc' ? 'desc' : 'asc') : 'asc'; table.order([index, newOrder]).draw(); }); }); </script> </body> </html>
关键细节说明
- 响应式布局:通过
flex-wrap: wrap和min-width实现,屏幕宽度不足300px时右侧表格自动移到左侧下方 - 动态拆分:
drawCallback会在每次筛选、排序后触发,自动计算当前可见行数并拆分,完美适配行数动态变化的场景 - 功能同步:克隆表格的筛选框和表头排序都绑定到主表格的事件,确保两个表格状态完全一致
- iframe支持:直接将此页面嵌入iframe即可,所有逻辑都在单个页面内,无需额外维护多份文件
备选方案:自定义列表的排序与筛选
如果表格方案不符合需求,这里提供列表的自定义实现,解决隐藏日期前缀排序、首字符排序和组合筛选问题:
HTML结构
<div class="list-container" style="margin:auto;width:90%;padding:10px;"> <div class="filters" style="margin-bottom:20px;display:flex;gap:10px;flex-wrap:wrap;"> <input type="text" id="place-filter" placeholder="Search Place" style="padding:5px;flex:1;min-width:200px;"> <input type="text" id="date-filter" placeholder="Search Date" style="padding:5px;flex:1;min-width:200px;"> <select id="sort-type" style="padding:5px;"> <option value="date">Date (hidden prefix)</option> <option value="place-first-char">Place First Character</option> </select> </div> <ul id="item-list" style="list-style:none;padding:0;"> <!-- 列表项示例:data-date-prefix存储8位格式的隐藏日期 --> <li data-date-prefix="20110425" style="padding:8px;border-bottom:1px solid #eee;">Edinburgh - 2011/04/25</li> <li data-date-prefix="20110725" style="padding:8px;border-bottom:1px solid #eee;">Tokyo - 2011/07/25</li> <!-- 更多列表项... --> </ul> </div>
JavaScript逻辑
$(document).ready(function() { var $listItems = $('#item-list li'); // 组合筛选函数 function filterItems() { var placeFilter = $('#place-filter').val().toLowerCase(); var dateFilter = $('#date-filter').val().toLowerCase(); $listItems.each(function() { var text = $(this).text().toLowerCase(); var matchesPlace = text.includes(placeFilter); var matchesDate = text.includes(dateFilter); $(this).toggle(matchesPlace && matchesDate); }); // 筛选完成后自动重新排序 sortItems(); } // 自定义排序函数 function sortItems() { var sortType = $('#sort-type').val(); var visibleItems = $('#item-list li:visible').toArray(); visibleItems.sort(function(a, b) { if (sortType === 'date') { // 按隐藏的8位日期前缀排序 var dateA = $(a).data('date-prefix'); var dateB = $(b).data('date-prefix'); return dateA.localeCompare(dateB); } else if (sortType === 'place-first-char') { // 按Place首字符排序 var charA = $(a).text().charAt(0).toLowerCase(); var charB = $(b).text().charAt(0).toLowerCase(); return charA.localeCompare(charB); } }); // 重新插入排序后的列表项 $('#item-list').html(visibleItems); } // 绑定筛选与排序事件 $('#place-filter, #date-filter').on('keyup change', filterItems); $('#sort-type').on('change', sortItems); // 页面初始化时执行一次排序 sortItems(); });
说明
- 隐藏日期排序:通过
data-date-prefix属性存储8位格式的日期(如20110425),排序时直接比较该值,避免显示格式影响排序结果 - 首字符排序:提取列表项文本的第一个字符进行本地化比较,确保排序逻辑符合语言习惯
- 组合筛选:同时匹配地点和日期的筛选条件,筛选后自动触发排序,保证结果始终有序
内容的提问来源于stack exchange,提问作者aprilius
相关产品推荐
相关产品推荐

