2016-11-15 3 views
0

Basierend auf this question, schrieb ich den folgenden Code:auf DOMNodeInserted funktioniert nicht wie erwartet?

$(function() { 
    $(document).on('DOMNodeInserted',"span:contains('Suggested Post')", function() { 
     console.log("New Suggested Post found"); 
    }) 
}) 

Als ich die Seite nach unten scrollen und diese Elemente werden erstellt, ich die Konsole Meldung nicht sehen, ich sehe erwarten. Wenn ich jedoch in der Konsole $("span:contains('Suggested Post')").length manuell eingabe, wird die Ausgabe weiter erhöht.

Ideen?

Snippet von @Barmar angefordert. Es verhält sich nicht genau wie meine realen Szenario, aber es ist immer noch nicht richtig ...

$(document).on('DOMNodeInserted', "div:contains('Banana')", function() { 
 
    console.log("new banana detected!"); 
 
}); 
 

 
$('#btn').on('click', function() { 
 
    var fruit = ''; 
 
    switch (Math.floor((Math.random() * 3) + 1)) { 
 
    case 1: 
 
     fruit = 'Apple' 
 
     break; 
 
    case 2: 
 
     fruit = 'Orange' 
 
     break; 
 
    case 3: 
 
     fruit = 'Banana' 
 
     break; 
 
    default: 
 
     fruit = "WTF" 
 
    } 
 
    $('#fakeDocument').append('<div>' + fruit + '</div>'); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="fakeDocument"> 
 
    <strong>Banana Detector</strong> 
 
    <button id="btn" type="button">Add Banana!</button> 
 
</div>

+0

Mit Ihrer Delegation wird der Handler nur ausgelöst, wenn die Elemente ** innen geschaffen ** ein Element, das den Wähler übereinstimmt, nicht, wenn das Element, das den Selektor erstellt wird übereinstimmt. – Barmar

+0

ahhhhh, ich verstehe. Irgendwelche Vorschläge für Änderungen? –

+0

Hmm, da könnte ich mich irren. https://www.w3.org/TR/DOM-Level-3-Events/#event-type-DOMNodeInserted sagt, dass "event.target" der einzufügende Knoten ist, nicht der Container. Und jQuery stimmt den Selektor mit dem Ziel überein. – Barmar

Antwort

1

Sie müssen die Delegation auf die unmittelbare Mutter der Elemente binden, die sein werden eingefügt.

Der Grund dafür ist, dass das Ereignis DOMNodeInserted aufblitzt. Wenn Sie es an einen äußeren Container binden, wird es zu einem enthaltenden DIV blubbern, und dieser DIV wird :contains(Banana) wegen der Banana Detector Überschrift entsprechen. Und selbst wenn Sie das aus dem Container verschieben, wird es aufgrund zuvor hinzugefügter Knoten, die Banana enthalten, übereinstimmen.

Aus diesem Grund gab es zwei Auslösungen, wenn eine tatsächliche Übereinstimmung gefunden wurde: Es wurde einmal für das neue übereinstimmende Element und erneut für den Container ausgelöst, der immer übereinstimmt.

Ich dachte ursprünglich, dass event.StopPropagation() das Problem lösen würde, aber es tut es nicht. Es verhindert doppelte Auslösungen, wenn es ein tatsächliches Spiel gibt. Aber es wird immer noch feuern, wenn es keine Übereinstimmung gibt - das Ereignis feuert nicht auf das neue Element (weil es nicht passt), so dass event.stopPropagation() nicht ausgeführt wird, so dass es zu dem Container ausbrennt, der übereinstimmt.

$("#fakeDocument").on('DOMNodeInserted', "div:contains('Banana')", function() { 
 
    console.log("new banana detected!"); 
 
}); 
 

 
$('#btn').on('click', function() { 
 
    var fruit = ''; 
 
    switch (Math.floor((Math.random() * 3) + 1)) { 
 
    case 1: 
 
     fruit = 'Apple' 
 
     break; 
 
    case 2: 
 
     fruit = 'Orange' 
 
     break; 
 
    case 3: 
 
     fruit = 'Banana' 
 
     break; 
 
    default: 
 
     fruit = "WTF" 
 
    } 
 
    $('#fakeDocument').append('<div>' + fruit + '</div>'); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="fakeDocument"> 
 
    <strong>Banana Detector</strong> 
 
    <button id="btn" type="button">Add Banana!</button> 
 
</div>

Verwandte Themen