如何简化带互斥条件的表格筛选器实现,提升扩展性?
问题描述
我需要制作一个用于选择数组筛选器的表格,需满足特定条件(例如不能同时选中client和user)。目前我通过为表格单元格设置ID实现了该功能,但当需要新增单元格时,现有代码扩展性差,难以维护,请问有没有更简洁的实现方案?
现有实现代码
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"/> <style> .blank_row { height: 50px !important; } </style> <table id="graphTable" class="table table-sm table-bordered"> <thead> <tr> <th class="border" colspan="3">FILTER</th> </tr> <tr> <th>DATE</th> <th>CLIENT</th> <th>USER</th> </tr> </thead> <tbody> <tr class="blank_row"> <td id="date"></td> <td id="client"></td> <td id="user"></td> </tr> </tbody> </table> <script> jQuery(document).ready(function($) { filter = { date: 0, client: 0, user: 0 }; $(".blank_row > td").click(function() { if (filter['date'] == 0 && $(this).attr('id') == 'date') { filter[$(this).attr('id')] = 1; $(this).addClass("bg-success"); } else if (filter['date'] == 1 && $(this).attr('id') == 'date') { $(this).removeClass("bg-success"); filter[$(this).attr('id')] = 0; } if (filter['client'] == 0 && filter['user'] == 0 && $(this).attr('id') != 'date') { filter[$(this).attr('id')] = 1; $(this).addClass("bg-success"); } else if (filter['client'] == 1 || filter['user'] == 1) { $(this).removeClass("bg-success"); filter[$(this).attr('id')] = 0; } console.log($(this).attr('id')); console.log(filter); }); }); </script>
优化方案
这是个很常见的扩展性问题,核心就是要把筛选规则和JS逻辑解耦,不用每次加新选项都改代码对吧?我给你一个基于**数据属性(data-*)**的方案,以后新增筛选器只需要在HTML里配置规则,JS完全不用动:
优化后的代码
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"/> <style> .blank_row { height: 50px !important; } .filter-cell { cursor: pointer; } /* 加个鼠标指针提示可点击 */ </style> <table id="graphTable" class="table table-sm table-bordered"> <thead> <tr> <th class="border" colspan="4">FILTER</th> <!-- 新增了GROUP选项示例 --> </tr> <tr> <th>DATE</th> <th>CLIENT</th> <th>USER</th> <th>GROUP</th> <!-- 新增的筛选器 --> </tr> </thead> <tbody> <tr class="blank_row"> <!-- 用data-filter-id替代id,data-mutual-group定义互斥组:同一组的选项不能同时选中 --> <td class="filter-cell" data-filter-id="date" data-mutual-group="none"></td> <td class="filter-cell" data-filter-id="client" data-mutual-group="client-user-group"></td> <td class="filter-cell" data-filter-id="user" data-mutual-group="client-user-group"></td> <td class="filter-cell" data-filter-id="group" data-mutual-group="client-user-group"></td> <!-- 和client、user互斥 --> </tr> </tbody> </table> <script> jQuery(document).ready(function($) { // 自动从HTML读取所有筛选器,初始化状态,不用手动写每个选项 const filterState = {}; $('.filter-cell').each(function() { const filterId = $(this).data('filter-id'); filterState[filterId] = 0; }); $('.filter-cell').click(function() { const $cell = $(this); const filterId = $cell.data('filter-id'); const mutualGroup = $cell.data('mutual-group'); const isActive = filterState[filterId] === 1; if (isActive) { // 取消当前选中状态 $cell.removeClass('bg-success'); filterState[filterId] = 0; } else { // 先清空同一互斥组的所有选中状态 if (mutualGroup !== 'none') { $(`.filter-cell[data-mutual-group="${mutualGroup}"]`).each(function() { const otherFilterId = $(this).data('filter-id'); $(this).removeClass('bg-success'); filterState[otherFilterId] = 0; }); } // 选中当前单元格 $cell.addClass('bg-success'); filterState[filterId] = 1; } console.log('当前点击:', filterId); console.log('筛选状态:', filterState); }); }); </script>
方案优势
- 高扩展性:新增筛选器时,只需在HTML里加一个
<td>,配置data-filter-id和data-mutual-group(如果需要互斥),JS完全不用修改 - 规则可视化:互斥规则直接写在HTML属性里,一眼就能看出哪些选项不能同时选中
- 自动初始化:不用手动维护
filter对象的初始值,JS会自动扫描所有筛选器并初始化状态 - 灵活的互斥配置:可以把任意多个筛选器分到同一互斥组,比如示例里新增的
GROUP选项,和CLIENT、USER自动实现三者互斥
内容的提问来源于stack exchange,提问作者rmarquet21
相关产品推荐
相关产品推荐

