通过fetch刷新下拉框时出现选项重复填充、取值相同的异常问题
下拉框刷新触发选项重复填充异常
场景说明
- 现有实现:通过
fetch接口请求填充select下拉框,页面初始加载时可正常生成3个对应Pump的下拉选项 - 新增功能:配置「刷新服务」按钮,计划点击时先清空select下所有原有option,再重新拉取接口数据完成填充
- 原自定义清除逻辑代码:
for (let i = length - 1; i >= 0; i--) { select.remove(i); } setTimeout(fetchUrl, 1000);
异常表现
预期效果:下拉框仅展示3组不重复的Pump选项
Option1 Pump1 Option2 Pump2 Option3 Pump3实际运行结果:重新拉取后下拉框累计生成6组完全重复的选项,原有选项未被成功清除
Option1 Pump1 Option2 Pump2 Option3 Pump3 Option4 Pump1 Option5 Pump2 Option6 Pump3
现有填充逻辑代码
fetch(url) .then((res) => res.json()) .then((data) => { opt = data; console.log(data); opt.forEach((item) => { console.log(item); options.push({ v: item.name, t: item.name, }); }); let selectTag = $("#node-input-options")[0]; let elem = $("#node-input-filter"); // 遍历生成的options数组,循环创建<option>元素追加到select下 for (let i = 0; i < options.length; i++) { let value = options[i].v; let text = options[i].t; $("#node-input-options").append( $("<option></option>").attr("value", value).text(text) ); } })
问题成因
两个叠加的逻辑漏洞直接导致了重复问题:
- 全局options数组未做重置:
options是定义在fetch逻辑外部的全局数组,每次触发刷新调用fetch时,都会把新拉取到的3条数据push到原有已经存了3条数据的数组里,数组长度直接从3变成6,后续循环遍历追加选项时自然会把累计的6条全部渲染出来 - DOM节点的清除逻辑执行不到位:原代码里的循环移除逻辑存在两个问题:一是移除时直接按索引调用
select.remove(i),当子节点长度动态变化时,索引对应的节点会出现错位删除;二是清除逻辑和fetch执行没有形成严格的时序绑定,存在“先追加新DOM、后调用清除逻辑”的执行错位,部分旧option根本没被删掉
修复实现方案
按逻辑拆分修正两个环节即可实现刷新后正确填充:
- 在fetch拿到响应数据、组装options数组前,先把全局options数组重置为空,避免历史数据累计污染
- 在每次向select追加新选项前,通过jQuery的
empty()API一次性清空select下所有子option,替代原有容易出错的循环索引删除逻辑
修正后的核心代码参考:
fetch(url) .then((res) => res.json()) .then((data) => { // 重置全局options数组,避免历史数据累计 options = []; opt = data; opt.forEach((item) => { options.push({ v: item.name, t: item.name, }); }); // 清空select下所有旧选项,替代手动循环删除逻辑 $("#node-input-options").empty(); // 遍历新的options数组,追加新选项 for (let i = 0; i < options.length; i++) { let value = options[i].v; let text = options[i].t; $("#node-input-options").append( $("<option></option>").attr("value", value).text(text) ); } })
内容的提问来源于stack exchange,提问作者ivexy
相关产品推荐
相关产品推荐

