如何实现Select2多选组件跨选联动禁用?(jQuery)
解决Select2跨多选框互斥禁用的问题
我看了你的代码,问题主要出在事件绑定逻辑混乱和没有通知Select2更新UI这两点上,咱们一步步来修正:
问题分析
- 嵌套事件绑定导致逻辑失效:你在
change事件内部又绑定了select2:select和select2:unselect,这会导致每次触发change都会新增一次事件监听,不仅逻辑混乱,而且你维护的selections数组也没法正确同步选中状态。 - 禁用原生option后未刷新Select2:Select2是基于原生select封装的,直接修改原生option的
disabled属性后,Select2不会自动感知到变化,必须手动触发刷新才能让禁用状态在界面上生效。 - 缺少取消选中时的恢复逻辑:你只处理了选中时禁用对应选项,但没写取消选中后恢复启用的代码,这样之前禁用的选项永远不会被放开。
修正后的完整代码
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/> <link href="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/css/select2.min.css" rel="stylesheet"/> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/js/select2.min.js"></script> <span>Table Header</span> <select id="tableHeader" class="select2 select2-multiple" style="width: 100%" multiple="multiple" data-placeholder="Choose"> <option value="Geo">Geo</option> <option value="Region">Region</option> <option value="Country">Country</option> <option value="Order Numer">Order Numer</option> <option value="Order Value">Order Value</option> <option value="Brand">Brand</option> <option value="Quantity">Quantity</option> <option value="Price">Price</option> <option value="Revenue">Revenue</option> <option value="Currency">Currency</option> <option value="Created Date">Created Date</option> <option value="Created By">Created By</option> </select> <br> <span>Table Body</span> <select id="tableBody" class="select2 select2-multiple" style="width: 100%" multiple="multiple" data-placeholder="Choose"> <option value="Geo">Geo</option> <option value="Region">Region</option> <option value="Country">Country</option> <option value="Order Numer">Order Numer</option> <option value="Order Value">Order Value</option> <option value="Brand">Brand</option> <option value="Quantity">Quantity</option> <option value="Price">Price</option> <option value="Revenue">Revenue</option> <option value="Currency">Currency</option> <option value="Created Date">Created Date</option> <option value="Created By">Created By</option> </select> <script> $(document).ready(function() { // 搜索匹配输入的函数 function matchCustom(params, data) { if ($.trim(params.term) === '') { return data; } if (typeof data.text === 'undefined') { return null; } if (data.text.toUpperCase().indexOf(params.term.toUpperCase()) > -1) { var modifiedData = $.extend({}, data, true); modifiedData.text += ''; return modifiedData; } return null; } // 初始化两个Select2 $(".select2").select2({ matcher: matchCustom }); // 封装一个通用函数:根据选中值禁用/启用另一个下拉框的选项 function syncDisabledOptions(sourceSelectId, targetSelectId) { var selectedValues = $('#' + sourceSelectId).val() || []; // 获取源下拉框的选中值,为空则设为空数组 var $targetSelect = $('#' + targetSelectId); // 先恢复所有选项为启用状态 $targetSelect.find('option').prop('disabled', false); // 禁用选中值对应的选项 selectedValues.forEach(function(val) { $targetSelect.find('option[value="' + val + '"]').prop('disabled', true); }); // 通知Select2刷新UI,否则禁用状态不会显示 $targetSelect.trigger('change'); } // 监听tableHeader的选中变化 $('#tableHeader').on('select2:select select2:unselect', function() { syncDisabledOptions('tableHeader', 'tableBody'); }); // 监听tableBody的选中变化 $('#tableBody').on('select2:select select2:unselect', function() { syncDisabledOptions('tableBody', 'tableHeader'); }); }); </script>
关键改进点
- 使用Select2原生事件:直接监听
select2:select和select2:unselect事件,这两个事件是Select2专门用于多选框选中/取消选中的,比原生change事件更精准。 - 封装通用函数减少重复代码:把禁用/启用选项的逻辑抽成
syncDisabledOptions函数,避免重复写两遍相同的代码,也更易维护。 - 先恢复再禁用:每次处理前先把目标下拉框的所有选项恢复启用,再禁用需要排除的选项,确保逻辑不会出现残留的禁用状态。
- 触发Select2刷新:修改原生option属性后,调用
trigger('change')让Select2重新渲染UI,这样禁用状态才能在界面上显示出来。
内容的提问来源于stack exchange,提问作者DevTN
相关产品推荐
相关产品推荐

