模块化JS实现:点击复选框启用对应单选按钮的最佳实践
解决方案:模块化实现复选框控制单选按钮启用状态
好的,咱们一步步来解决你的问题,同时兼顾模块化代码的设计原则~
关于cacheDom的模块化疑问
你担心“单独选中每个复选框是否会降低模块化程度”——答案是确实会。如果硬编码每个复选框的ID(比如$('#weekly'), $('#monthly')),会让JS代码和DOM结构强绑定:以后新增一个Yearly的字段集,或者修改现有复选框的ID,你都得同步修改JS代码,这违背了模块化“低耦合、高复用”的核心原则。
更好的做法是用通用选择器定位复选框,比如基于它们所在的fieldset.report-type容器来选择,这样不管新增多少个同类字段集,代码都不需要修改,扩展性更强。
模块化实现代码
我们基于你现有的模块结构,添加单选按钮的控制逻辑,同时优化模块化程度:
HTML部分(移除内联样式,让结构更整洁)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <span class="btn" id="setScheduleBtn">Set Schedule</span> <div id="reportSchedule" name="reportSchedule"> <fieldset class="report-type"> <legend> <input type="checkbox" name="weekly" id="weekly"> <label for="weekly">Weekly:</label> </legend> <input type="radio" id="week" name="week" checked disabled> <label for="week">3 Months</label> </fieldset> <fieldset class="report-type"> <legend> <input type="checkbox" name="monthly" id="monthly"> <label for="monthly">Monthly:</label> </legend> <input type="radio" id="monthly1" name="monr" disabled> <label for="monthly1">1 Month</label> <input type="radio" id="monthly3" name="monr" disabled> <label for="monthly3">3 Months</label> <input type="radio" id="monthly6" name="monr" disabled> <label for="monthly6">6 Months</label> </fieldset> <fieldset class="report-type"> <legend> <input type="checkbox" name="quarterly" id="quarterly"> <label for="quarterly">Quarterly:</label> </legend> <input type="radio" id="quarterly3" name="quar" disabled> <label for="quarterly3">3 Months</label> <input type="radio" id="quarterly6" name="quar" disabled> <label for="quarterly6">6 Months</label> <input type="radio" id="quarterly12" name="quar" disabled> <label for="quarterly12">12 Months</label> </fieldset> </div>
配套CSS(替代内联样式,实现样式与结构分离)
.report-type { width: 32%; display: inline-block; } #reportSchedule { display: none; /* 初始隐藏,配合slideToggle效果 */ }
模块化JS实现
/******************/ /** Set Schedule **/ /******************/ (function() { var schedule = { report: [], template: $('#report_schedule').html(), // 初始化入口 init: function() { this.cacheDom(); this.bindEvents(); }, // 缓存DOM元素(用通用选择器提升模块化) cacheDom: function() { this.$setScheduleBtn = $('#setScheduleBtn'); this.$reportSchedule = $('#reportSchedule'); // 选择所有report-type字段集内的复选框,无需关心具体数量和ID this.$checkBoxes = $('.report-type input[type="checkbox"]'); }, // 绑定事件 bindEvents: function() { this.$setScheduleBtn.click(this.showReportScheduler.bind(this)); // 给所有复选框绑定状态切换事件 this.$checkBoxes.change(this.toggleRadioState.bind(this)); }, // 显示/隐藏调度器面板 showReportScheduler: function() { this.$reportSchedule.slideToggle("fast"); }, // 新增:切换当前字段集内单选按钮的启用状态 toggleRadioState: function(e) { const $currentCheckbox = $(e.target); // 找到当前复选框所属的字段集容器 const $parentFieldset = $currentCheckbox.closest('.report-type'); // 获取容器内的所有单选按钮 const $radios = $parentFieldset.find('input[type="radio"]'); // 根据复选框状态切换单选按钮的禁用属性 $radios.prop('disabled', !$currentCheckbox.is(':checked')); // 可选优化:启用时默认选中第一个单选按钮,提升用户体验 if ($currentCheckbox.is(':checked') && !$radios.is(':checked')) { $radios.first().prop('checked', true); } } }; schedule.init(); })();
代码核心亮点
- 模块化优化:
cacheDom用通用选择器定位复选框,新增字段集时JS代码无需修改,完全解耦DOM结构和业务逻辑。 - 局部控制:通过
closest('.report-type')精准定位当前复选框的父容器,只修改该容器内的单选按钮状态,不会影响其他字段集。 - 逻辑简洁:用
prop('disabled', !$checkbox.is(':checked'))一行代码完成状态切换,可读性强。 - 可扩展性:后续如果要添加新的调度类型,只需要复制现有
fieldset结构即可,JS代码完全不用改动。
内容的提问来源于stack exchange,提问作者Imnotapotato
相关产品推荐
相关产品推荐

