{"id":742,"date":"2024-02-23T07:07:08","date_gmt":"2024-02-23T07:07:08","guid":{"rendered":"https:\/\/webdevs.blog\/pl\/?p=742"},"modified":"2026-02-20T07:28:07","modified_gmt":"2026-02-20T07:28:07","slug":"event-delegation-w-js","status":"publish","type":"post","link":"https:\/\/webdevs.blog\/pl\/event-delegation-w-js\/","title":{"rendered":"Event delegation w JS"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webdevs.blog\/pl\/wp-content\/uploads\/sites\/2\/2024\/02\/Event-Delegation.jpeg\" alt=\"\" class=\"wp-image-744\" width=\"1122\" height=\"673\" srcset=\"https:\/\/webdevs.blog\/pl\/wp-content\/uploads\/sites\/2\/2024\/02\/Event-Delegation.jpeg 1000w, https:\/\/webdevs.blog\/pl\/wp-content\/uploads\/sites\/2\/2024\/02\/Event-Delegation-300x180.jpeg 300w, https:\/\/webdevs.blog\/pl\/wp-content\/uploads\/sites\/2\/2024\/02\/Event-Delegation-768x461.jpeg 768w\" sizes=\"auto, (max-width: 1122px) 100vw, 1122px\" \/><\/figure>\n\n\n\n<p>Eventy w JavaScript mog\u0105 by\u0107 propagowane, co oznacza, \u017ce zdarzenie wywo\u0142ane na elemencie potomnym przechodzi przez wszystkich rodzic\u00f3w. Zastosowanie wzorca Event Delegation polega na obs\u0142udze zdarzenia w elemencie nadrz\u0119dnym. Jest przydatny, gdy mamy wiele podobnych element\u00f3w, a ich obs\u0142uga nie r\u00f3\u017cni si\u0119 w znacznym stopniu. To, co jest wa\u017cne w tym wzorcu, to propagacja zdarze\u0144 oraz cel (target) zdarzenia. Poni\u017cej przedstawiono kilka przyk\u0142ad\u00f3w u\u017cycia.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prosty przyk\u0142ad<\/h2>\n\n\n\n<p><br>Dobrym przyk\u0142adem ilustruj\u0105cym zastosowanie wzorca Event Delegation b\u0119dzie menu, gdzie chcemy niestandardowo obs\u0142u\u017cy\u0107 nawigacj\u0119.<\/p>\n\n\n\n<p>Struktura HTML b\u0119dzie wygl\u0105da\u0142a mniej wi\u0119cej tak:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"menu\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">data-page<\/span>=<span class=\"hljs-string\">\"home\"<\/span>&gt;<\/span>Home<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">data-page<\/span>=<span class=\"hljs-string\">\"about\"<\/span>&gt;<\/span>About<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">data-page<\/span>=<span class=\"hljs-string\">\"contact\"<\/span>&gt;<\/span>Contact<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Do obs\u0142ugi nawigacji mogliby\u015bmy tworzy\u0107 listenery na klikni\u0119cia w poszczeg\u00f3lne elementy button, ale dzi\u0119ki wzorcowi Event Delegation obs\u0142u\u017cymy klikni\u0119cia w buttony za pomoc\u0105 <strong>jednego listenera<\/strong>, kt\u00f3ry podepniemy pod div <code>#menu<\/code><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-built_in\">document<\/span>.getElementById(<span class=\"hljs-string\">'menu'<\/span>).addEventListener(<span class=\"hljs-string\">'click'<\/span>, (event) =&gt; {\n  <span class=\"hljs-keyword\">const<\/span> page = event.target.dataset.page;\n  <span class=\"hljs-keyword\">if<\/span> (page) {\n    <span class=\"hljs-comment\">\/\/ obs\u0142uga nawigacji<\/span>\n    <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">`Navigate to <span class=\"hljs-subst\">${navigation}<\/span>`<\/span>);\n  }\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Oczywi\u015bcie, je\u015bli mieliby\u015bmy wi\u0119cej menu w r\u00f3\u017cnych miejscach na stronie i obs\u0142ugiwali\u015bmy je w ten sam spos\u00f3b, nic nie stoi na przeszkodzie, aby\u015bmy obs\u0142u\u017cyli nawigacj\u0119 nas\u0142uchuj\u0105c na elemencie<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Okre\u015blanie Celu (Target)<\/h2>\n\n\n\n<p>We\u017amy teraz na tapet\u0119 bardziej skomplikowany przyk\u0142ad u\u017cycia wzorca Event Delegation. B\u0119dzie to pod\u015bwietlenie wiersza w tabeli po klikni\u0119ciu, niezale\u017cnie czy klikniemy w kom\u00f3rk\u0119 czy w sam wiersz. Dodatkowo chcemy wykluczy\u0107 z tej logiki pod\u015bwietlanie nag\u0142\u00f3wk\u00f3w tabeli.<\/p>\n\n\n\n<p>HTML tabeli:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">table<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"table\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">thead<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">tr<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">th<\/span>&gt;<\/span>Kolumna 1<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">th<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">th<\/span>&gt;<\/span>Kolumna 2<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">th<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">th<\/span>&gt;<\/span>Kolumna 3<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">th<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">th<\/span>&gt;<\/span>Kolumna 4<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">th<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">tr<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">thead<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">tbody<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">tr<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">td<\/span>&gt;<\/span>Wiersz 1, Kolumna 1<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">td<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">td<\/span>&gt;<\/span>Wiersz 1, Kolumna 2<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">td<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">td<\/span>&gt;<\/span>Wiersz 1, Kolumna 3<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">td<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">td<\/span>&gt;<\/span>Wiersz 1, Kolumna 4<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">td<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">tr<\/span>&gt;<\/span>\n    ....\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">tbody<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">table<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>W JS b\u0119dziemy nas\u0142uchiwa\u0107 na elemencie <code>#table<\/code><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-built_in\">document<\/span>.getElementById(<span class=\"hljs-string\">'table'<\/span>).addEventListener(<span class=\"hljs-string\">'click'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\">event<\/span>) <\/span>{\n  <span class=\"hljs-keyword\">let<\/span> row = event.target;\n\n  <span class=\"hljs-keyword\">while<\/span> (row.tagName !== <span class=\"hljs-keyword\">this<\/span>) {\n    <span class=\"hljs-keyword\">if<\/span> (row.tagName === <span class=\"hljs-string\">'TR'<\/span>) {\n      <span class=\"hljs-keyword\">if<\/span> (row.parentElement.tagName === <span class=\"hljs-string\">'TBODY'<\/span>) {\n\n        <span class=\"hljs-comment\">\/\/ obs\u0142uga pod\u015bwietlenia wiersza<\/span>\n        <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">'Highlight row'<\/span>, row);\n      }\n\n      <span class=\"hljs-keyword\">return<\/span>;\n    }\n    \n    row = row.parentElement;\n  }\n});\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Za pomoc\u0105 p\u0119tli while sprawdzamy, czy zmienna <strong>row <\/strong>to element <code>TR<\/code>. Je\u015bli tak, to sprawdzamy, czy <strong>row<\/strong> znajduje si\u0119 w <code>TBODY<\/code>. Je\u015bli oba warunki s\u0105 spe\u0142nione, mo\u017cemy pod\u015bwietli\u0107 wiersz i zako\u0144czy\u0107 funkcj\u0119. Je\u015bli <strong>row<\/strong> znajdowa\u0142by si\u0119 w <code>THEAD<\/code>, wtedy nie obs\u0142u\u017cymy pod\u015bwietlenia i zako\u0144czymy funkcj\u0119.<\/p>\n\n\n\n<p>W ten spos\u00f3b mo\u017cemy okre\u015bli\u0107 odpowiedni cel (target) i wykona\u0107 na nim potrzebne operacje.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Podsumowanie<\/h2>\n\n\n\n<p>Event Delegation jest skutecznym narz\u0119dziem, gdy musimy obs\u0142u\u017cy\u0107 wiele element\u00f3w w ten sam spos\u00f3b lub gdy elementy w drzewie DOM s\u0105 usuwane lub dodawane, a my musimy reagowa\u0107 na ich zdarzenia. Jest wydajny, poniewa\u017c zamiast nas\u0142uchiwa\u0107 wielu element\u00f3w, nas\u0142uchujemy tylko na jednym.<\/p>\n\n\n\n<p>Musimy pami\u0119ta\u0107, \u017ce by ten wzorzec dzia\u0142a\u0142, zdarzenie musi by\u0107 propagowane a\u017c do elementu, w kt\u00f3rym zawarta jest obs\u0142uga. Oznacza to, \u017ce nie mo\u017cemy wcze\u015bniej wywo\u0142a\u0107 metody <code>event.stopPropagation()<\/code>. Czasami mog\u0105 by\u0107 te\u017c potrzebne dodatkowe dzia\u0142ania do ustalenia odpowiedniego celu (targetu).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Event Delegation to kluczowy element warsztatu ka\u017cdego programisty, kt\u00f3ry pragnie zoptymalizowa\u0107 swoje projekty webowe.Poznaj, jak unikn\u0105\u0107 nadmiernego nas\u0142uchiwania na poszczeg\u00f3lne elementy i spraw, aby Twoje interakcje z drzewem DOM by\u0142y bardziej wydajne.<\/p>\n","protected":false},"author":17,"featured_media":744,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,10,14,4],"tags":[89,58,63],"class_list":["post-742","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dobre-praktyki","category-js","category-optymalizacja","category-web-development","tag-it","tag-js","tag-optimization"],"_links":{"self":[{"href":"https:\/\/webdevs.blog\/pl\/wp-json\/wp\/v2\/posts\/742","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/webdevs.blog\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/webdevs.blog\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/webdevs.blog\/pl\/wp-json\/wp\/v2\/users\/17"}],"replies":[{"embeddable":true,"href":"https:\/\/webdevs.blog\/pl\/wp-json\/wp\/v2\/comments?post=742"}],"version-history":[{"count":7,"href":"https:\/\/webdevs.blog\/pl\/wp-json\/wp\/v2\/posts\/742\/revisions"}],"predecessor-version":[{"id":763,"href":"https:\/\/webdevs.blog\/pl\/wp-json\/wp\/v2\/posts\/742\/revisions\/763"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/webdevs.blog\/pl\/wp-json\/wp\/v2\/media\/744"}],"wp:attachment":[{"href":"https:\/\/webdevs.blog\/pl\/wp-json\/wp\/v2\/media?parent=742"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/webdevs.blog\/pl\/wp-json\/wp\/v2\/categories?post=742"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/webdevs.blog\/pl\/wp-json\/wp\/v2\/tags?post=742"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}