2016-01-11 6 views
6

Mam ustawione dwa programy obsługi zdarzeń dla zdarzenia kliknięcia. Jeden na wszystkich w tabeli i inny ogólny w dokumencie.Zmiana innerHTML powoduje przerwanie parentNode, gdy znacznik zakotwiczenia zostanie nadpisany? Jak naprawić?

Część kodu w instrukcji obsługi <th> zmienia innerHTML klikniętego elementu. Co najważniejsze, w tagu th znajduje się znacznik zakotwiczenia.

Część kodu w procedurze sprawdzania dokumentu sprawdza węzeł nadrzędny klikniętego elementu.

Pojawia się , że te dwa fakty powodują problem. Jeśli skomentuję linię modyfikacji innerHTML, wszystko działa poprawnie. Jeśli jednak go zostawię, otrzymam "null" dla elementu o wartości parentNode.

Czy jest to znany problem, a jeśli tak, jakie jest rozwiązanie? Czy jest to błąd w Chrome, czy w jaki sposób JavaScript/DOM zachowuje się z jakiegoś powodu?

function isInside(eChild, eParent) { 
 
    alert('element is ' + eChild); 
 
    if (eChild === eParent) { 
 
    return true; 
 
    } 
 

 
    if (eChild === document) { 
 
    return false; 
 
    } 
 

 
    return isInside(eChild.parentNode, eParent); 
 
} 
 

 
function init1() { 
 
    document.getElementById('th').addEventListener('click', function(e) { 
 
    document.getElementById('th').innerHTML = '<a href="#">Changed</a>'; 
 
    }); 
 
} 
 

 
function init2() { 
 
    document.addEventListener('click', function(e) { 
 
    if (isInside(e.target, document.getElementById('table'))) { 
 
     alert('found in table'); 
 
    } else { 
 
     alert('not found in table'); 
 
    } 
 
    }); 
 
} 
 

 
init1(); 
 
init2();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 

 
<table id="table"> 
 
    <thead> 
 
    <tr> 
 
     <th id="th"><a href="#">Click me</a> 
 
     </th> 
 
    </tr> 
 
    </thead> 
 
</table>

Jeśli wykomentuj linię

document.getElementById('th').innerHTML = '<a href="#">Changed</a>'; 

w JavaScripcie będą mieli do pożądanego zachowania.

Zakładam, że dzieje się tak, ponieważ zdarzenie wystrzeliwuje na <a>, a nie na <th>, a następnie zamieniam tę kotwicę na nową w wywołaniu innerHTML. Jak to naprawić?

+4

możesz udostępnić odpowiedni fragment kodu? – gurvinder372

+1

Bez fragmentu, niejasny co do części DOM jest dotknięty –

+0

Nie jest to żaden problem, i jest prawdopodobnie coś innego w kodzie. Podaj odpowiedni kod, który pokazuje ten problem, w przeciwnym razie to pytanie nie jest tematem. –

Odpowiedz

3

Dzieje się tak, ponieważ element, który został kliknięty, nie istnieje już w dokumencie w momencie, gdy żądany jest jego węzeł nadrzędny. Zastąpiłeś go zupełnie innym elementem.

Zamiast zmieniać innerHTML rodzica, a więc zastępując element, który został kliknięty nowym elementem, wystarczy zmienić istniejący element.

Mam skondensowane pełną prezentację poniżej, aby zaoszczędzić miejsce, jednak mięso w roztworze jest tutaj:

var th = document.getElementById('th'); 
var link = th.querySelector('a'); 

th.addEventListener('click', function(e) { 
    link.textContent = 'Changed'; 
}); 

Oto demo:

function isInside(eChild, eParent) { 
 
    alert('element is ' + eChild); 
 
    if (eChild === eParent) return true; 
 
    if (eChild === document) return false; 
 
    return isInside(eChild.parentNode, eParent); 
 
} 
 

 
var th = document.getElementById('th'); 
 
var link = th.querySelector('a'); 
 

 
th.addEventListener('click', function(e) { 
 
    link.textContent = 'Changed'; 
 
}); 
 

 
document.addEventListener('click', function(e) { 
 
    if (isInside(e.target, document.getElementById('table'))) alert('found in table'); 
 
    else alert('not found in table'); 
 
});
<table id="table"><thead><tr><th id="th"><a href="#">Click me</a></th></tr></thead></table>