iPhone端DataTables列切换按钮点击后样式不切换的问题修复
解决iPhone上DataTables列切换按钮样式不更新的问题
我用DataTables结合Bootstrap实现了表格列的显示/隐藏切换功能,通过按钮控制列可见性:列显示时按钮应用btn-secondary样式,隐藏时应用btn-outline-secondary样式。该功能在桌面端运行正常,但在iPhone设备上测试时,点击按钮隐藏列后,列已成功隐藏,但按钮样式无法切换回btn-outline-secondary。
原始代码示例
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"> <span>Show / Hide: </span> <button type="button" class='toggle-vis btn btn-outline-secondary' data-column='0'>ID</button> <button type="button" class='toggle-vis btn btn-outline-secondary' data-column='1'>Date</button> <button type="button" class='toggle-vis btn btn-outline-secondary' data-column='2'>Time</button> <button type="button" class='toggle-vis btn btn-outline-secondary' data-column='3'>Item</button> <button type="button" class='toggle-vis btn btn-outline-secondary' data-column='4'>Quantity</button> <table class='table table-bordered' id='dataTable' width='100%' cellspacing='0'> <thead> <tr> <th>ID</th> <th>Date</th> <th>Time</th> <th>Item</th> <th>Quantity</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>1/10</td> <td>12:00</td> <td>Apple</td> <td>3</td> </tr> <tr> <td>2</td> <td>4/10</td> <td>14:00</td> <td>Apple</td> <td>1</td> </tr> <tr> <td>3</td> <td>4/10</td> <td>14:00</td> <td>Orange</td> <td>3</td> </tr> </table> <script src='https://code.jquery.com/jquery-3.7.0.js' type='text/javascript'></script> <script src='https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js' type='text/javascript'></script> <script> $(document).ready(function() { // Initialize DataTable const table = $('#dataTable').DataTable({ "columnDefs": [ // Hide columns based on unique column indices { "visible": false, "targets": 2 } ] }); // Handle button click events document.querySelectorAll('button.toggle-vis').forEach((el) => { el.addEventListener('click', function(e) { e.preventDefault(); let columnIdx = e.target.getAttribute('data-column'); let column = table.column(columnIdx); // Toggle the visibility column.visible(!column.visible()); if (column.visible()) { e.target.classList.replace('btn-outline-secondary', 'btn-secondary'); } else { e.target.classList.replace('btn-secondary', 'btn-outline-secondary'); } }); }); // Initialize button classes based on initial column visibility table.columns().every(function() { var column = this; var columnIdx = column.index(); if (column.visible()) { var button = document.querySelector("button.toggle-vis[data-column='" + columnIdx + "']"); button.classList.replace('btn-outline-secondary', 'btn-secondary'); } if (!column.visible()) { var button = document.querySelector("button.toggle-vis[data-column='" + columnIdx + "']"); button.classList.replace('btn-secondary', 'btn-outline-secondary'); } }); }); </script>
问题根源
iPhone的Safari浏览器在处理点击事件时,e.target可能指向按钮内部的文本节点而非按钮元素本身,导致后续的class操作无法作用到正确的DOM元素。此外,classList.replace()方法在目标类不存在时不会执行任何操作,也可能导致样式切换失效。
修复方案
- 使用
this替代e.target:在事件监听器中,this始终指向触发事件的按钮元素,避免因事件冒泡导致的目标元素错误。 - 替换class操作逻辑:先移除不需要的类,再添加目标类,确保样式切换的可靠性,避免依赖
replace()的局限性。
修改后的JavaScript代码
$(document).ready(function() { // Initialize DataTable const table = $('#dataTable').DataTable({ "columnDefs": [ // Hide columns based on unique column indices { "visible": false, "targets": 2 } ] }); // Handle button click events document.querySelectorAll('button.toggle-vis').forEach((el) => { el.addEventListener('click', function(e) { e.preventDefault(); // 使用this获取当前按钮元素,避免e.target指向子节点 const button = this; let columnIdx = button.getAttribute('data-column'); let column = table.column(columnIdx); // Toggle the visibility column.visible(!column.visible()); // 先移除旧类再添加新类,确保样式切换生效 if (column.visible()) { button.classList.remove('btn-outline-secondary'); button.classList.add('btn-secondary'); } else { button.classList.remove('btn-secondary'); button.classList.add('btn-outline-secondary'); } }); }); // Initialize button classes based on initial column visibility table.columns().every(function() { var column = this; var columnIdx = column.index(); var button = document.querySelector("button.toggle-vis[data-column='" + columnIdx + "']"); if (column.visible()) { button.classList.remove('btn-outline-secondary'); button.classList.add('btn-secondary'); } else { button.classList.remove('btn-secondary'); button.classList.add('btn-outline-secondary'); } }); });
可选优化:使用jQuery简化代码
如果项目已引入jQuery,可使用jQuery的事件绑定和class操作提升兼容性与可读性:
$(document).ready(function() { const table = $('#dataTable').DataTable({ "columnDefs": [ { "visible": false, "targets": 2 } ] }); // jQuery绑定点击事件,自动处理目标元素问题 $('.toggle-vis').on('click', function(e) { e.preventDefault(); const $button = $(this); const columnIdx = $button.data('column'); const column = table.column(columnIdx); column.visible(!column.visible()); // 链式调用切换class if (column.visible()) { $button.removeClass('btn-outline-secondary').addClass('btn-secondary'); } else { $button.removeClass('btn-secondary').addClass('btn-outline-secondary'); } }); // 初始化按钮样式 table.columns().every(function() { const column = this; const $button = $(`.toggle-vis[data-column="${column.index()}"]`); if (column.visible()) { $button.removeClass('btn-outline-secondary').addClass('btn-secondary'); } else { $button.removeClass('btn-secondary').addClass('btn-outline-secondary'); } }); });
内容的提问来源于stack exchange,提问作者jayden__2002
相关产品推荐
相关产品推荐

