2009-08-25 4 views
1

Cette question est similaire à my last question about "too much recursion" errors in jQuery, mais impliquant des gestionnaires en ligne. J'ai un élément dans un autre. Les deux ont des gestionnaires d'événements personnalisés avec le même nom. L'élément externe a un gestionnaire traditionnel et l'élément interne a un gestionnaire en direct. Lorsque j'essaie de déclencher l'événement sur l'élément externe, mon navigateur fait une pause pendant un moment, puis une erreur me dit "trop ​​de récursivité".erreur «trop de récursivité» avec les gestionnaires en direct dans jQuery 1.3.2

J'ai lu sur le live handler documentation page que je peux empêcher le bouillonnement d'un gestionnaire en direct en retournant false dans la fonction gestionnaire. Cependant, j'ai essayé cela et cela ne semble pas faire la différence. D'une manière ou d'une autre, la fonction externe semble être appelée de nombreuses fois lorsque j'essaie de l'appeler une seule fois.

Comment puis-je résoudre ce problème? Est-il possible d'avoir des gestionnaires avec le même nom comme ça, ou dois-je trouver des noms différents? Vous pouvez tester le problème en utilisant ce code:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html><head> 
<title>live event handler test</title> 
</head> 
<body> 
<div id="outer"> 
    <div id="inner"> 
    </div> 
</div> 
<script type="text/javascript" src="jquery-1.3.2.min.js"></script> 
<script type="text/javascript"> 
$("#outer").bind("test", function() { 
    $("#inner").trigger("test"); 
}); 

$("#inner").live("test", function() { 
    return false; 
}); 

$(function() { 
    $("#outer").trigger("test"); 
}); 
</script> 
</body></html> 
+0

Joli coffret complet. –

Répondre

1

Regardez le rappel de #outer:

$("#outer").bind("test", function() { 
    $("#inner").trigger("test"); 
}); 

Vous déclenchez "test" sur #inner, mais #inner est un enfant de #outer, de sorte que l'événement « bouillonne » à #outer et le processus se répète (jusqu'à ce qu'il explose).

Modifier: comme @skiwi souligne, si vous utilisez live() sur les deux #outer et #inner cela fonctionne. C'est parce que "return false;" fonctionne comme event.stopImmediatePropagation() dans ce cas. De même, si vous utilisez bind() sur les deux cela fonctionne aussi. C'est parce que "return false;" fonctionne comme event.stopPropagation() dans ce cas.

Toutefois, vous mélangez les deux et en utilisant bind sur #outer et live sur #inner. L'effet net est que le déclenchement de votre événement n'exécutera jamais votre gestionnaire live (c'est-à-dire return false ne sera jamais exécuté) car it is bound to the document, et l'événement n'obtiendra jamais une chance d'atteindre le document en raison du débordement de la pile.

Edit 2:

est-il un moyen d'empêcher la formation de bulles sur l'événement intérieur? (utilisant live()?)

Nope. Voir jquery Event.stopPropagation() seems not to work une meilleure explication.

+0

Pourquoi l'événement sur #inner monte-t-il à #out?La déclaration "return false" n'est-elle pas censée empêcher cela? –

+0

Pourquoi existe-t-il un débordement de pile? Si le gestionnaire en ligne n'est jamais exécuté, je ne vois pas pourquoi la fonction externe serait appelée plus d'une fois. –

+0

@ mikez302: bulles 'trigger'. Aussi simple que cela. Enlevez 'live' et le problème existe toujours. 'live' n'a rien à voir avec ça. Le libellé de mon dernier paragraphe porte à confusion, je pense. Le problème est toujours ce que je déclare dans le premier paragraphe. –

0

Il semble que la combinaison de live et de bind pour un événement personnalisé a un bug? Pas vraiment sûr de ce qui se passe réellement. Si vous utilisez dir.s cela fonctionne:

$("#outer").live("test", function() { 
    console.log("outer"); 
    $("#inner").trigger("test"); 
}); 

$("#inner").live("test", function() { 
    console.log("inner"); 
    return false; 
}); 

$(function() { 
    $("#outer").trigger("test"); 
}); 

N'a pas creusé dans la source trop mais il semble que bind ne tient pas compte de la valeur de retour de la fonction.

+0

Vraiment? J'ai essayé de changer les noms de "test" pour "cliquer" et j'obtiens exactement la même erreur. –

+0

Oui, j'avais tort. Mise à jour ma réponse – seth

Questions connexes