为什么修改option显隐状态后HTML的<Select>下拉框无法正常更新?
问题成因
- 原生
<select>的下拉选项由浏览器内核独立渲染,会在首次展开时缓存当前option列表的状态快照,你通过CSS修改option的display属性后,浏览器不会主动更新这份缓存,首次展开读取的还是修改前的旧状态,第二次展开才会重新读取DOM的最新状态。 - 你代码中加入了300ms的防抖延迟,如果输入搜索内容后300ms内就点击下拉框,此时防抖回调还未执行,所有option还处于你提前设置的
display: none状态,自然展示为空,等第二次点击时防抖逻辑已经执行完成,符合条件的option已经设置为显示,就可以正常展示。
解决方案
可以选择以下任意一种方案修复:
方案1:移除防抖+强制刷新select缓存
如果你的option数量不多,完全可以去掉防抖逻辑,同时修改完option显隐后触发一次select重绘,强制浏览器更新缓存:
$(document).on("input propertychange change", ".searchField", function() { var searchInput = $(this).val(); var $dropdown = $(".monsterDropdown"); if (searchInput == "") { $(".monsterOption").css("display", "block"); } else { $(".monsterOption").css("display", "none"); $(".monsterOption").each(function(i, ele) { var monstername = $(this).data("monstername"); if (monstername.toLowerCase().indexOf(searchInput.toLowerCase()) != -1) { $dropdown.val(monstername); $(this).css("display", "block"); } }); } // 强制刷新select缓存,触发重绘 $dropdown.prop('disabled', true); $dropdown.prop('disabled', false); });
如果必须保留防抖优化,只需在防抖回调的末尾添加上述强制刷新select的两行代码即可,同时可考虑加入搜索中的状态提示,避免用户在防抖等待期点击下拉时看到空列表。
方案2:重构为option动态增删逻辑(兼容性最好)
部分旧版浏览器不支持修改option的display属性,直接动态生成符合条件的option列表兼容性更强:
// 先把所有原始option存为全局缓存 const allOptions = Array.from($(".monsterOption")).map(ele => ({ name: $(ele).data("monstername"), text: $(ele).text() })); $(document).on("input propertychange change", ".searchField", function() { const searchInput = $(this).val().toLowerCase(); const $dropdown = $(".monsterDropdown"); // 清空现有option $dropdown.empty(); // 筛选符合条件的option插入 const matchedOptions = allOptions.filter(item => item.name.toLowerCase().includes(searchInput) ); matchedOptions.forEach(item => { $dropdown.append(`<option class="monsterOption" data-monstername="${item.name}">${item.text}</option>`) }); // 自动选中第一个匹配项 if(matchedOptions.length) $dropdown.val(matchedOptions[0].name); });
内容的提问来源于stack exchange,提问作者ObedMarsh
相关产品推荐
相关产品推荐

