{"id":529,"date":"2011-09-19T19:18:13","date_gmt":"2011-09-19T17:18:13","guid":{"rendered":"https:\/\/sgaul.de\/?p=529"},"modified":"2014-03-13T21:34:54","modified_gmt":"2014-03-13T20:34:54","slug":"event-trigger-live-delegate-problem","status":"publish","type":"post","link":"https:\/\/sgaul.de\/2011\/09\/19\/event-trigger-live-delegate-problem\/","title":{"rendered":"J-Query-Probleme mit $.event.trigger(), live() und delegate()"},"content":{"rendered":"

In meinem Artikel \u201eJ-Query-Projekte mit Events strukturieren<\/a>\u201c habe ich die M\u00f6glichkeit vorgestellt, Javascript-Events mittels J-Querys $.event.trigger(eventName)<\/span> auszul\u00f6sen. Man sollte sich aber bewusst sein, dass diese Methode nicht mit Elementen zusammenarbeitet, die mittels live()<\/span> oder delegate()<\/span> an einen Event gebunden wurden.<\/p>\n

Bind(), live() und delegate() \u2013 der Test<\/h2>\n

Ein kleiner Test macht deutlich, dass $.event.trigger(eventName)<\/span> wenig kooperativ ist:<\/p>\n

$(function() {\r\n\r\n    $('.class0').bind('myevent', function() {\r\n        $(this).css('backgroundColor', '#f99');\r\n    });\r\n\r\n    $('.class1').live('myevent', function() {\r\n        $(this).css('backgroundColor', '#f99');\r\n    });\r\n\r\n    $('body').delegate('.class2', 'myevent', function() {\r\n        $(this).css('backgroundColor', '#f99');\r\n    });\r\n\r\n    $.each([0,1,2,3,4,5], function(i) {\r\n        $('
<\/div>')\r\n .appendTo('body')\r\n .text('class' + i)\r\n .addClass('class' + i);\r\n });\r\n\r\n $('.class3').bind('myevent', function() {\r\n $(this).css('backgroundColor', '#f99');\r\n });\r\n\r\n $('.class4').live('myevent', function() {\r\n $(this).css('backgroundColor', '#f99');\r\n });\r\n\r\n $('body').delegate('.class5', 'myevent', function() {\r\n $(this).css('backgroundColor', '#f99');\r\n });\r\n\r\n $.event.trigger('myevent');\r\n});<\/pre>\n

Lediglich das Element, welches nach seiner Erzeugung mittels bind()<\/span> verbunden wurde, reagiert auf den Trigger:<\/p>\n

\"\"<\/a>Hintergrund<\/h2>\n

Dass lediglich Bind funktioniert, hat einen einfachen, aber sehr technischen Hintergrund.<\/p>\n

Beim Aufruf von $(selektor).bind()<\/span> sucht J-Query alle Elemente, auf die der Selektor passt und verkn\u00fcpft sie mit dem entsprechenden Event-Handler. Zus\u00e4tzlich wird ein Zeiger in $.event<\/span> hinterlegt. Dies macht man sich bei $.event.trigger()<\/span> zunutze.<\/p>\n

Bei live()<\/span> und delegate()<\/span> wird hingegen gar nicht gepr\u00fcft, welche Elemente auf den Selektor passen. Stattdessen wird das Event auf der fast h\u00f6chsten Ebene des DOM-Baums registriert, dem Document<\/span>. Klickt man nun auf ein Div im Body, wird der erzeugte Click-Event nach oben durchgereicht: Div > Body > HTML > Document. So kann jede Schicht f\u00fcr sich selbst auf das Event reagieren, da ein Klick auf das Div auch ein Klick auf den Body der Seite ist.<\/p>\n

Dieses Verhalten bezeichnet man als Event-Propagation<\/em> und wird von J-Query genutzt: Der Handler $(‚div‘).live(‚click‘, callback)<\/span> registriert einen Klick-Eventhandler im Document. Kommt nun ein solcher Event im Document an, guckt der Handler nach, ob der Event \u00fcber ein Element ging, das auf den Selektor (im Beispiel ‚div‘) passt. Falls ja, f\u00fchrt er auf all diesen passenden Elementen die Funktion callback<\/span> aus.<\/p>\n

Die Variante delegate()<\/span> verh\u00e4lt sich, von ihren Kleinigkeiten abgesehen, genauso.<\/p>\n

Diese Funktionsweise erkl\u00e4rt, warum Live und Delegate auch auf Elemente wirken, die zur Zeit der Festlegung noch nicht vorhanden waren: Der Selektor wird nach der Event-Ausl\u00f6sung, nicht zur Event-Registrierung ausgewertet.<\/p>\n

M\u00f6gliche L\u00f6sungen<\/h2>\n

Eine wirklich gute L\u00f6sung konnte ich bisher nicht finden.<\/p>\n

Man k\u00f6nnte jedem Event eine Klasse zuweisen, und statt auf $.event<\/span> auf $(‚.eventklasse‘)<\/span> triggern. Diese L\u00f6sung wird sehr oft vorgeschlagen. Ich hingegen finde sie nicht sch\u00f6n: Klassen geh\u00f6ren zum HTML der Seite. Sie sollten nicht f\u00fcr Zwecke missbraucht werden, die nur Javascript tangieren.<\/p>\n

Derzeit versuche ich auf Live und Delegate zu verzichten. In den meisten F\u00e4llen ist dies problemlos m\u00f6glich: Entweder das Element existiert bereits im DOM-Baum (steht also direkt in der HTML-Datei) oder ich registriere den Event-Handler direkt nach der Erzeugung des Elements. F\u00fcr beides kann man dann einfach Bind nehmen.<\/p>\n","protected":false},"excerpt":{"rendered":"

In meinem Artikel \u201eJ-Query-Projekte mit Events strukturieren\u201c habe ich die M\u00f6glichkeit vorgestellt, Javascript-Events mittels J-Querys $.event.trigger(eventName) auszul\u00f6sen. Man sollte sich aber bewusst sein, dass diese Methode nicht mit Elementen zusammenarbeitet, die mittels live() oder delegate() an einen Event gebunden wurden.<\/p>\n","protected":false},"author":1,"featured_media":530,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[91],"tags":[149,158,111],"_links":{"self":[{"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/posts\/529"}],"collection":[{"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/comments?post=529"}],"version-history":[{"count":5,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/posts\/529\/revisions"}],"predecessor-version":[{"id":535,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/posts\/529\/revisions\/535"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/media\/530"}],"wp:attachment":[{"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/media?parent=529"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/categories?post=529"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/tags?post=529"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}