记一次切换tab页后,切换回原有tab页点击弹出框,弹出框内下拉选项点击无法展开显示的问题
背景描述:
在大屏某一个tab页中,设置有一个弹出框按钮,当用户点击该按钮弹出弹出框,弹出框内有两个下拉选项,第一个下拉框没有前置限制,第二个下拉选项依赖第一个下拉选项选择后进行对应获取选项。
在页面初始化后,第一次操作上述弹出框,第一个第二个弹出框都可以展开选择,如下图所示:

但是当在此操作后,在切换其他tab页,然后再切换回该tab操作弹出框时,此时会出现第二个下拉框点击没有反应,不显示下拉选项,如下图所示:

查看日志都正常。
因为这个项目是嵌入在Vue项目中,每个tab页点击时,都会调用该tab页包含的各显示方法,出现问题的tab页在vue的相关调用是:
1 case 'taskControl': 2 contentJs.ForthTab(); 3 break;
在js中被调用:
1 export function ForthTab() { 2 $(function () { 3 taskDistribution(); 4 }) 5 }
而实际上,整个tab问题页的显示都是靠调用taskDistribution()这一个方法。
问题发现:
通过走读taskDistribution()方法内部,发现出现问题的下拉框div对象设置的监听事件
1 // 修改点击任务描述下拉框的事件 (点击交替显示和隐藏) 2 taskDescSelect.addEventListener('click', function () { 3 //无人系统已选择的情况下 4 if (modalSystem.value) { 5 const isVisible = taskDescMenu.style.display === 'block';//判断当前任务下拉选项是否已经显示了 6 taskDescMenu.style.display = isVisible ? 'none' : 'block';//如果已显示,则此次点击后隐藏;如果未显示,则此次点击后显示 7 8 } 9 });
初始化页面后,第一次操作不会出现问题,但是当切换其他tab,再切回该tab页时,因为页面不是重新初始化,所以该div对象又被设置了一次点击事件监听,这就使得同一个对象监听两次,这样当点击事件触发时,会导致下拉选项来回显示和隐藏,这就可能:
1 - 同一个点击事件被触发多次
2 - 事件处理逻辑相互干扰,导致下拉列表的显示/隐藏逻辑混乱
3 - 第一次点击可能显示下拉列表,但第二次点击立即隐藏它,看起来就像下拉列表没有正常展开
解决方法:
在调用显示函数前,先执行一下清除taskDescSelect绑定的事件,然后再正常执行显示函数的调用。
调用处的修改代码如下:
1 export function ForthTab() { 2 $(function () { 3 // 清理可能存在的事件监听器 4 const taskDescSelect = document.getElementById('taskDescSelect'); 5 if (taskDescSelect) { 6 const newElement = taskDescSelect.cloneNode(true); 7 taskDescSelect.parentNode.replaceChild(newElement, taskDescSelect); 8 } 9 taskDistribution(); 10 }) 11 }
这段代码通过以下方式解决了问题:
1. DOM元素克隆与替换 : cloneNode(true) 创建了元素的深度复制,包括其所有属性但不包括事件监听器
2. 替换原始元素 :使用 replaceChild 方法用新元素替换原始元素,这样原始元素上绑定的所有事件监听器都被清除了
3. 重新初始化 :当 taskDistribution() 函数执行时,它会在这个全新的DOM元素上绑定事件监听器,避免了多重绑定
详解:replaceChild(newChild, oldChild)
这是 DOM(文档对象模型)中的一个方法,用于在父节点中将某个子节点替换为另一个节点。
parentNode:父元素节点,调用这个方法的元素必须是其父节点。newChild:要用来替换的新的节点(可以是新创建的,也可以是已存在的节点)。oldChild:要被替换掉的子节点(必须是当前parentNode的直接子节点)。

浙公网安备 33010602011771号