記一次切換tab頁后,切換回原有tab頁點擊彈出框,彈出框內(nèi)下拉選項點擊無法展開顯示的問題
背景描述:
在大屏某一個tab頁中,設(shè)置有一個彈出框按鈕,當(dāng)用戶點擊該按鈕彈出彈出框,彈出框內(nèi)有兩個下拉選項,第一個下拉框沒有前置限制,第二個下拉選項依賴第一個下拉選項選擇后進(jìn)行對應(yīng)獲取選項。
在頁面初始化后,第一次操作上述彈出框,第一個第二個彈出框都可以展開選擇,如下圖所示:

但是當(dāng)在此操作后,在切換其他tab頁,然后再切換回該tab操作彈出框時,此時會出現(xiàn)第二個下拉框點擊沒有反應(yīng),不顯示下拉選項,如下圖所示:

查看日志都正常。
因為這個項目是嵌入在Vue項目中,每個tab頁點擊時,都會調(diào)用該tab頁包含的各顯示方法,出現(xiàn)問題的tab頁在vue的相關(guān)調(diào)用是:
1 case 'taskControl': 2 contentJs.ForthTab(); 3 break;
在js中被調(diào)用:
1 export function ForthTab() { 2 $(function () { 3 taskDistribution(); 4 }) 5 }
而實際上,整個tab問題頁的顯示都是靠調(diào)用taskDistribution()這一個方法。
問題發(fā)現(xiàn):
通過走讀taskDistribution()方法內(nèi)部,發(fā)現(xiàn)出現(xiàn)問題的下拉框div對象設(shè)置的監(jiān)聽事件
1 // 修改點擊任務(wù)描述下拉框的事件 (點擊交替顯示和隱藏) 2 taskDescSelect.addEventListener('click', function () { 3 //無人系統(tǒng)已選擇的情況下 4 if (modalSystem.value) { 5 const isVisible = taskDescMenu.style.display === 'block';//判斷當(dāng)前任務(wù)下拉選項是否已經(jīng)顯示了 6 taskDescMenu.style.display = isVisible ? 'none' : 'block';//如果已顯示,則此次點擊后隱藏;如果未顯示,則此次點擊后顯示 7 8 } 9 });
初始化頁面后,第一次操作不會出現(xiàn)問題,但是當(dāng)切換其他tab,再切回該tab頁時,因為頁面不是重新初始化,所以該div對象又被設(shè)置了一次點擊事件監(jiān)聽,這就使得同一個對象監(jiān)聽兩次,這樣當(dāng)點擊事件觸發(fā)時,會導(dǎo)致下拉選項來回顯示和隱藏,這就可能:
1 - 同一個點擊事件被觸發(fā)多次
2 - 事件處理邏輯相互干擾,導(dǎo)致下拉列表的顯示/隱藏邏輯混亂
3 - 第一次點擊可能顯示下拉列表,但第二次點擊立即隱藏它,看起來就像下拉列表沒有正常展開
解決方法:
在調(diào)用顯示函數(shù)前,先執(zhí)行一下清除taskDescSelect綁定的事件,然后再正常執(zhí)行顯示函數(shù)的調(diào)用。
調(diào)用處的修改代碼如下:
1 export function ForthTab() { 2 $(function () { 3 // 清理可能存在的事件監(jiān)聽器 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) 創(chuàng)建了元素的深度復(fù)制,包括其所有屬性但不包括事件監(jiān)聽器
2. 替換原始元素 :使用 replaceChild 方法用新元素替換原始元素,這樣原始元素上綁定的所有事件監(jiān)聽器都被清除了
3. 重新初始化 :當(dāng) taskDistribution() 函數(shù)執(zhí)行時,它會在這個全新的DOM元素上綁定事件監(jiān)聽器,避免了多重綁定
詳解:replaceChild(newChild, oldChild)
這是 DOM(文檔對象模型)中的一個方法,用于在父節(jié)點中將某個子節(jié)點替換為另一個節(jié)點。
parentNode:父元素節(jié)點,調(diào)用這個方法的元素必須是其父節(jié)點。newChild:要用來替換的新的節(jié)點(可以是新創(chuàng)建的,也可以是已存在的節(jié)點)。oldChild:要被替換掉的子節(jié)點(必須是當(dāng)前parentNode的直接子節(jié)點)。

浙公網(wǎng)安備 33010602011771號