diff --git a/apps/web/src/__generated__/questions/quiz/describe-event-bubbling/locales/en-US.json b/apps/web/src/__generated__/questions/quiz/describe-event-bubbling/locales/en-US.json index e5bf6a80d..19f34d562 100644 --- a/apps/web/src/__generated__/questions/quiz/describe-event-bubbling/locales/en-US.json +++ b/apps/web/src/__generated__/questions/quiz/describe-event-bubbling/locales/en-US.json @@ -5,5 +5,5 @@ "title": "Describe event bubbling in JavaScript and browsers", "gitHubEditUrl": "https://github.com/yangshun/top-javascript-interview-questions/blob/main/questions/describe-event-bubbling/en-US.mdx" }, - "solution": "var Component=(()=>{var s=Object.create;var o=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var p=Object.getPrototypeOf,m=Object.prototype.hasOwnProperty;var b=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),v=(t,e)=>{for(var i in e)o(t,i,{get:e[i],enumerable:!0})},r=(t,e,i,c)=>{if(e&&typeof e==\"object\"||typeof e==\"function\")for(let l of g(e))!m.call(t,l)&&l!==i&&o(t,l,{get:()=>e[l],enumerable:!(c=u(e,l))||c.enumerable});return t};var f=(t,e,i)=>(i=t!=null?s(p(t)):{},r(e||!t||!t.__esModule?o(i,\"default\",{value:t,enumerable:!0}):i,t)),y=t=>r(o({},\"__esModule\",{value:!0}),t);var d=b((D,a)=>{a.exports=_jsx_runtime});var B={};v(B,{default:()=>E,frontmatter:()=>w});var n=f(d()),w={title:\"Describe event bubbling in JavaScript and browsers\"};function h(t){let e=Object.assign({h2:\"h2\",p:\"p\",hr:\"hr\",strong:\"strong\",a:\"a\",pre:\"pre\",code:\"code\",ul:\"ul\",li:\"li\",h3:\"h3\"},t.components);return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.h2,{children:\"TL;DR\"}),`\n`,(0,n.jsx)(e.p,{children:\"Event bubbling is a DOM event propagation mechanism where an event (e.g. a click), starts at the target element and bubbles up to the root of the document. This allows ancestor elements to also respond to the event.\"}),`\n`,(0,n.jsx)(e.p,{children:\"Event bubbling is essential for event delegation, where a single event handler manages events for multiple child elements, enhancing performance and code simplicity. While convenient, failing to manage event propagation properly can lead to unintended behavior, such as multiple handlers firing for a single event.\"}),`\n`,(0,n.jsx)(e.hr,{}),`\n`,(0,n.jsx)(e.h2,{children:\"What is event bubbling?\"}),`\n`,(0,n.jsx)(e.p,{children:\"Event bubbling is a propagation mechanism in the DOM (Document Object Model) where an event, such as a click or a keyboard event, is first triggered on the target element that initiated the event and then propagates upward (bubbles) through the DOM tree to the root of the document.\"}),`\n`,(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:\"Note\"}),\": even before the event bubbling phase happens is the \",(0,n.jsx)(e.a,{href:\"/questions/quiz/describe-event-capturing\",children:\"event capturing\"}),\" phase which is the opposite of bubbling where the event goes down from the document root to the target element.\"]}),`\n`,(0,n.jsx)(e.h2,{children:\"Bubbling phase\"}),`\n`,(0,n.jsx)(e.p,{children:\"During the bubbling phase, the event starts at the target element and bubbles up through its ancestors in the DOM hierarchy. This means that the event handlers attached to the target element and its ancestors can all potentially receive and respond to the event.\"}),`\n`,(0,n.jsx)(e.p,{children:\"Here's an example using modern ES6 syntax to demonstrate event bubbling:\"}),`\n`,(0,n.jsx)(e.pre,{live:!0,children:(0,n.jsx)(e.code,{className:\"language-js\",children:`// HTML:\n//
\n// \n//
\nconst parentDiv = document.createElement('div');\nparentDiv.id = 'parent';\nconst button = document.createElement('button');\nbutton.id = 'child';\nparentDiv.appendChild(button);\ndocument.body.appendChild(parentDiv);\n\nconst parent = document.getElementById('parent');\nconst child = document.getElementById('child');\n\nparent.addEventListener('click', () => {\n console.log('Parent element clicked');\n});\n\nchild.addEventListener('click', () => {\n console.log('Child element clicked');\n});\n\n// Simulate clicking the button:\nchild.click();\n`})}),`\n`,(0,n.jsx)(e.p,{children:'When you click the \"Click me!\" button, both the child and parent event handlers will be triggered due to the event bubbling.'}),`\n`,(0,n.jsx)(e.h2,{children:\"Stopping the bubbling\"}),`\n`,(0,n.jsxs)(e.p,{children:[\"Event bubbling can be stopped during the bubbling phase using the \",(0,n.jsx)(e.code,{children:\"stopPropagation()\"}),\" method. If an event handler calls \",(0,n.jsx)(e.code,{children:\"stopPropagation()\"}),\", it prevents the event from further bubbling up the DOM tree, ensuring that only the handlers of the elements up to that point in the hierarchy are executed.\"]}),`\n`,(0,n.jsx)(e.pre,{live:!0,children:(0,n.jsx)(e.code,{className:\"language-js\",children:`// HTML:\n//
\n// \n//
\nconst parentDiv = document.createElement('div');\nparentDiv.id = 'parent';\nconst button = document.createElement('button');\nbutton.id = 'child';\nparentDiv.appendChild(button);\ndocument.body.appendChild(parentDiv);\n\nconst parent = document.getElementById('parent');\nconst child = document.getElementById('child');\n\nparent.addEventListener('click', () => {\n console.log('Parent element clicked');\n});\n\nchild.addEventListener('click', (event) => {\n console.log('Child element clicked');\n event.stopPropagation(); // Stops propagation to parent\n});\n\n// Simulate clicking the button:\nchild.click();\n`})}),`\n`,(0,n.jsx)(e.h2,{children:\"Event delegation\"}),`\n`,(0,n.jsxs)(e.p,{children:[\"Event bubbling is the basis for a technique called \",(0,n.jsx)(e.a,{href:\"/questions/quiz/describe-event-delegation\",children:\"event delegation\"}),\", where you attach a single event handler to a common ancestor of multiple elements and use event delegation to handle events for those elements efficiently. This is particularly useful when you have a large number of similar elements, like a list of items, and you want to avoid attaching individual event handlers to each item.\"]}),`\n`,(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:\"language-js\",children:`parent.addEventListener('click', (event) => {\n if (event.target && event.target.id === 'child') {\n console.log('Child element clicked');\n }\n});\n`})}),`\n`,(0,n.jsx)(e.h2,{children:\"Benefits\"}),`\n`,(0,n.jsxs)(e.ul,{children:[`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Cleaner code:\"}),\" Reduced number of event listeners improves code readability and maintainability.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Efficient event handling:\"}),\" Minimizes performance overhead by attaching fewer listeners.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Flexibility:\"}),\" Allows handling events happening on child elements without directly attaching listeners to them.\"]}),`\n`]}),`\n`,(0,n.jsx)(e.h2,{children:\"Pitfalls\"}),`\n`,(0,n.jsxs)(e.ul,{children:[`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Accidental event handling:\"}),\" Be mindful that parent elements might unintentionally capture events meant for children. Use \",(0,n.jsx)(e.code,{children:\"event.target\"}),\" to identify the specific element that triggered the event.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Event order:\"}),\" Events bubble up in a specific order. If multiple parents have event listeners, their order of execution depends on the DOM hierarchy.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Over-delegation:\"}),\" While delegating events to a common ancestor is efficient, attaching a listener too high in the DOM tree might capture unintended events.\"]}),`\n`]}),`\n`,(0,n.jsx)(e.h2,{children:\"Use cases\"}),`\n`,(0,n.jsx)(e.p,{children:\"Here are some practical ways to use event bubbling to write better code.\"}),`\n`,(0,n.jsx)(e.h3,{children:\"Reducing code with event delegation\"}),`\n`,(0,n.jsx)(e.p,{children:'Imagine you have a product list with numerous items, each with a \"Buy Now\" button. Traditionally, you might attach a separate click event listener to each button:'}),`\n`,(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:\"language-js\",children:`// HTML:\n// \n\nconst item1Buy = document.getElementById('item1-buy');\nconst item2Buy = document.getElementById('item2-buy');\n\nitem1Buy.addEventListener('click', handleBuyClick);\nitem2Buy.addEventListener('click', handleBuyClick);\n\n// ... repeat for each item ...\n\nfunction handleBuyClick(event) {\n console.log('Buy button clicked for item:', event.target.id);\n}\n`})}),`\n`,(0,n.jsx)(e.p,{children:\"This approach becomes cumbersome as the number of items grows. Here's how event bubbling can simplify things:\"}),`\n`,(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:\"language-js\",children:`// HTML:\n// \n\nconst productList = document.getElementById('product-list');\n\nproductList.addEventListener('click', handleBuyClick);\n\nfunction handleBuyClick(event) {\n // Check if the clicked element is a button within the list\n if (event.target.tagName.toLowerCase() === 'button') {\n console.log('Buy button clicked for item:', event.target.textContent);\n }\n}\n`})}),`\n`,(0,n.jsxs)(e.p,{children:[\"By attaching the listener to the parent (\",(0,n.jsx)(e.code,{children:\"productList\"}),\") and checking the clicked element (\",(0,n.jsx)(e.code,{children:\"event.target\"}),\") within the handler, you achieve the same functionality with less code. This approach scales well when the items are dynamic as no new event handlers have to be added or removed when the list of items change.\"]}),`\n`,(0,n.jsx)(e.h3,{children:\"Dropdown menus\"}),`\n`,(0,n.jsx)(e.p,{children:\"Consider a dropdown menu where clicking anywhere on the menu element (parent) should close it. With event bubbling, you can achieve this with a single listener:\"}),`\n`,(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:\"language-js\",children:`// HTML:\n//
\n// \n// \n//
\n\nconst dropdown = document.getElementById('dropdown');\n\ndropdown.addEventListener('click', handleDropdownClick);\n\nfunction handleDropdownClick(event) {\n // Close the dropdown if clicked outside the button\n if (event.target !== dropdown.querySelector('button')) {\n console.log('Dropdown closed');\n // Your logic to hide the dropdown content\n }\n}\n`})}),`\n`,(0,n.jsxs)(e.p,{children:[\"Here, the click event bubbles up from the clicked element (button or list item) to the \",(0,n.jsx)(e.code,{children:\"dropdown\"}),\" element. The handler checks if the clicked element is not the \",(0,n.jsx)(e.code,{children:\"\n// \nconst parentDiv = document.createElement('div');\nparentDiv.id = 'parent';\nconst button = document.createElement('button');\nbutton.id = 'child';\nparentDiv.appendChild(button);\ndocument.body.appendChild(parentDiv);\n\nconst parent = document.getElementById('parent');\nconst child = document.getElementById('child');\n\nparent.addEventListener('click', () => {\n console.log('Parent element clicked');\n});\n\nchild.addEventListener('click', () => {\n console.log('Child element clicked');\n});\n\n// Simulate clicking the button:\nchild.click();\n`})}),`\n`,(0,n.jsx)(e.p,{children:'When you click the \"Click me!\" button, both the child and parent event handlers will be triggered due to the event bubbling.'}),`\n`,(0,n.jsx)(e.h2,{children:\"Stopping the bubbling\"}),`\n`,(0,n.jsxs)(e.p,{children:[\"Event bubbling can be stopped during the bubbling phase using the \",(0,n.jsx)(e.code,{children:\"stopPropagation()\"}),\" method. If an event handler calls \",(0,n.jsx)(e.code,{children:\"stopPropagation()\"}),\", it prevents the event from further bubbling up the DOM tree, ensuring that only the handlers of the elements up to that point in the hierarchy are executed.\"]}),`\n`,(0,n.jsx)(e.pre,{live:!0,children:(0,n.jsx)(e.code,{className:\"language-js\",children:`// HTML:\n//
\n// \n//
\nconst parentDiv = document.createElement('div');\nparentDiv.id = 'parent';\nconst button = document.createElement('button');\nbutton.id = 'child';\nparentDiv.appendChild(button);\ndocument.body.appendChild(parentDiv);\n\nconst parent = document.getElementById('parent');\nconst child = document.getElementById('child');\n\nparent.addEventListener('click', () => {\n console.log('Parent element clicked');\n});\n\nchild.addEventListener('click', (event) => {\n console.log('Child element clicked');\n event.stopPropagation(); // Stops propagation to parent\n});\n\n// Simulate clicking the button:\nchild.click();\n`})}),`\n`,(0,n.jsx)(e.h2,{children:\"Event delegation\"}),`\n`,(0,n.jsxs)(e.p,{children:[\"Event bubbling is the basis for a technique called \",(0,n.jsx)(e.a,{href:\"/questions/quiz/explain-event-delegation\",children:\"event delegation\"}),\", where you attach a single event handler to a common ancestor of multiple elements and use event delegation to handle events for those elements efficiently. This is particularly useful when you have a large number of similar elements, like a list of items, and you want to avoid attaching individual event handlers to each item.\"]}),`\n`,(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:\"language-js\",children:`parent.addEventListener('click', (event) => {\n if (event.target && event.target.id === 'child') {\n console.log('Child element clicked');\n }\n});\n`})}),`\n`,(0,n.jsx)(e.h2,{children:\"Benefits\"}),`\n`,(0,n.jsxs)(e.ul,{children:[`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Cleaner code:\"}),\" Reduced number of event listeners improves code readability and maintainability.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Efficient event handling:\"}),\" Minimizes performance overhead by attaching fewer listeners.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Flexibility:\"}),\" Allows handling events happening on child elements without directly attaching listeners to them.\"]}),`\n`]}),`\n`,(0,n.jsx)(e.h2,{children:\"Pitfalls\"}),`\n`,(0,n.jsxs)(e.ul,{children:[`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Accidental event handling:\"}),\" Be mindful that parent elements might unintentionally capture events meant for children. Use \",(0,n.jsx)(e.code,{children:\"event.target\"}),\" to identify the specific element that triggered the event.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Event order:\"}),\" Events bubble up in a specific order. If multiple parents have event listeners, their order of execution depends on the DOM hierarchy.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Over-delegation:\"}),\" While delegating events to a common ancestor is efficient, attaching a listener too high in the DOM tree might capture unintended events.\"]}),`\n`]}),`\n`,(0,n.jsx)(e.h2,{children:\"Use cases\"}),`\n`,(0,n.jsx)(e.p,{children:\"Here are some practical ways to use event bubbling to write better code.\"}),`\n`,(0,n.jsx)(e.h3,{children:\"Reducing code with event delegation\"}),`\n`,(0,n.jsx)(e.p,{children:'Imagine you have a product list with numerous items, each with a \"Buy Now\" button. Traditionally, you might attach a separate click event listener to each button:'}),`\n`,(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:\"language-js\",children:`// HTML:\n// \n\nconst item1Buy = document.getElementById('item1-buy');\nconst item2Buy = document.getElementById('item2-buy');\n\nitem1Buy.addEventListener('click', handleBuyClick);\nitem2Buy.addEventListener('click', handleBuyClick);\n\n// ... repeat for each item ...\n\nfunction handleBuyClick(event) {\n console.log('Buy button clicked for item:', event.target.id);\n}\n`})}),`\n`,(0,n.jsx)(e.p,{children:\"This approach becomes cumbersome as the number of items grows. Here's how event bubbling can simplify things:\"}),`\n`,(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:\"language-js\",children:`// HTML:\n// \n\nconst productList = document.getElementById('product-list');\n\nproductList.addEventListener('click', handleBuyClick);\n\nfunction handleBuyClick(event) {\n // Check if the clicked element is a button within the list\n if (event.target.tagName.toLowerCase() === 'button') {\n console.log('Buy button clicked for item:', event.target.textContent);\n }\n}\n`})}),`\n`,(0,n.jsxs)(e.p,{children:[\"By attaching the listener to the parent (\",(0,n.jsx)(e.code,{children:\"productList\"}),\") and checking the clicked element (\",(0,n.jsx)(e.code,{children:\"event.target\"}),\") within the handler, you achieve the same functionality with less code. This approach scales well when the items are dynamic as no new event handlers have to be added or removed when the list of items change.\"]}),`\n`,(0,n.jsx)(e.h3,{children:\"Dropdown menus\"}),`\n`,(0,n.jsx)(e.p,{children:\"Consider a dropdown menu where clicking anywhere on the menu element (parent) should close it. With event bubbling, you can achieve this with a single listener:\"}),`\n`,(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:\"language-js\",children:`// HTML:\n//
\n// \n// \n//
\n\nconst dropdown = document.getElementById('dropdown');\n\ndropdown.addEventListener('click', handleDropdownClick);\n\nfunction handleDropdownClick(event) {\n // Close the dropdown if clicked outside the button\n if (event.target !== dropdown.querySelector('button')) {\n console.log('Dropdown closed');\n // Your logic to hide the dropdown content\n }\n}\n`})}),`\n`,(0,n.jsxs)(e.p,{children:[\"Here, the click event bubbles up from the clicked element (button or list item) to the \",(0,n.jsx)(e.code,{children:\"dropdown\"}),\" element. The handler checks if the clicked element is not the \",(0,n.jsx)(e.code,{children:\"\n// \nconst parentDiv = document.createElement('div');\nparentDiv.id = 'parent';\nconst button = document.createElement('button');\nbutton.id = 'child';\nparentDiv.appendChild(button);\ndocument.body.appendChild(parentDiv);\n\nconst parent = document.getElementById('parent');\nconst child = document.getElementById('child');\n\nparent.addEventListener('click', () => {\n console.log('Parent element clicked');\n});\n\nchild.addEventListener('click', () => {\n console.log('Child element clicked');\n});\n\n// Simulate clicking the button:\nchild.click();\n`})}),`\n`,(0,e.jsx)(n.p,{children:\"\\u5F53\\u60A8\\u70B9\\u51FB\\u201CClick me!\\u201D\\u6309\\u94AE\\u65F6\\uFF0C\\u7531\\u4E8E\\u4E8B\\u4EF6\\u5192\\u6CE1\\uFF0C\\u5B50\\u5143\\u7D20\\u548C\\u7236\\u5143\\u7D20\\u7684\\u4E8B\\u4EF6\\u5904\\u7406\\u7A0B\\u5E8F\\u90FD\\u5C06\\u88AB\\u89E6\\u53D1\\u3002\"}),`\n`,(0,e.jsx)(n.h2,{children:\"\\u505C\\u6B62\\u5192\\u6CE1\"}),`\n`,(0,e.jsxs)(n.p,{children:[\"\\u53EF\\u4EE5\\u4F7F\\u7528 \",(0,e.jsx)(n.code,{children:\"stopPropagation()\"}),\" \\u65B9\\u6CD5\\u5728\\u5192\\u6CE1\\u9636\\u6BB5\\u505C\\u6B62\\u4E8B\\u4EF6\\u5192\\u6CE1\\u3002\\u5982\\u679C\\u4E8B\\u4EF6\\u5904\\u7406\\u7A0B\\u5E8F\\u8C03\\u7528 \",(0,e.jsx)(n.code,{children:\"stopPropagation()\"}),\"\\uFF0C\\u5B83\\u4F1A\\u963B\\u6B62\\u4E8B\\u4EF6\\u8FDB\\u4E00\\u6B65\\u5192\\u6CE1\\u5230 DOM \\u6811\\u4E2D\\uFF0C\\u786E\\u4FDD\\u4EC5\\u6267\\u884C\\u5C42\\u6B21\\u7ED3\\u6784\\u4E2D\\u8BE5\\u70B9\\u4E4B\\u524D\\u7684\\u5143\\u7D20\\u7684\\u5904\\u7406\\u7A0B\\u5E8F\\u3002\"]}),`\n`,(0,e.jsx)(n.pre,{live:!0,children:(0,e.jsx)(n.code,{className:\"language-js\",children:`// HTML:\n//
\n// \n//
\nconst parentDiv = document.createElement('div');\nparentDiv.id = 'parent';\nconst button = document.createElement('button');\nbutton.id = 'child';\nparentDiv.appendChild(button);\ndocument.body.appendChild(parentDiv);\n\nconst parent = document.getElementById('parent');\nconst child = document.getElementById('child');\n\nparent.addEventListener('click', () => {\n console.log('Parent element clicked');\n});\n\nchild.addEventListener('click', (event) => {\n console.log('Child element clicked');\n event.stopPropagation(); // Stops propagation to parent\n});\n\n// Simulate clicking the button:\nchild.click();\n`})}),`\n`,(0,e.jsx)(n.h2,{children:\"\\u4E8B\\u4EF6\\u59D4\\u6258\"}),`\n`,(0,e.jsxs)(n.p,{children:[\"\\u4E8B\\u4EF6\\u5192\\u6CE1\\u662F\\u79F0\\u4E3A \",(0,e.jsx)(n.a,{href:\"/questions/quiz/describe-event-delegation\",children:\"\\u4E8B\\u4EF6\\u59D4\\u6258\"}),\" \\u7684\\u6280\\u672F\\u7684\\u57FA\\u7840\\uFF0C\\u60A8\\u5C06\\u5355\\u4E2A\\u4E8B\\u4EF6\\u5904\\u7406\\u7A0B\\u5E8F\\u9644\\u52A0\\u5230\\u591A\\u4E2A\\u5143\\u7D20\\u7684\\u516C\\u5171\\u7956\\u5148\\uFF0C\\u5E76\\u4F7F\\u7528\\u4E8B\\u4EF6\\u59D4\\u6258\\u6765\\u6709\\u6548\\u5730\\u5904\\u7406\\u8FD9\\u4E9B\\u5143\\u7D20\\u7684\\u4E8B\\u4EF6\\u3002\\u5F53\\u60A8\\u6709\\u5927\\u91CF\\u76F8\\u4F3C\\u7684\\u5143\\u7D20\\uFF08\\u5982\\u9879\\u76EE\\u5217\\u8868\\uFF09\\u5E76\\u4E14\\u5E0C\\u671B\\u907F\\u514D\\u5C06\\u5355\\u72EC\\u7684\\u4E8B\\u4EF6\\u5904\\u7406\\u7A0B\\u5E8F\\u9644\\u52A0\\u5230\\u6BCF\\u4E2A\\u9879\\u76EE\\u65F6\\uFF0C\\u8FD9\\u7279\\u522B\\u6709\\u7528\\u3002\"]}),`\n`,(0,e.jsx)(n.pre,{children:(0,e.jsx)(n.code,{className:\"language-js\",children:`parent.addEventListener('click', (event) => {\n if (event.target && event.target.id === 'child') {\n console.log('Child element clicked');\n }\n});\n`})}),`\n`,(0,e.jsx)(n.h2,{children:\"\\u4F18\\u70B9\"}),`\n`,(0,e.jsxs)(n.ul,{children:[`\n`,(0,e.jsxs)(n.li,{children:[(0,e.jsx)(n.strong,{children:\"\\u66F4\\u7B80\\u6D01\\u7684\\u4EE3\\u7801\\uFF1A\"}),\" \\u51CF\\u5C11\\u4E8B\\u4EF6\\u76D1\\u542C\\u5668\\u7684\\u6570\\u91CF\\uFF0C\\u63D0\\u9AD8\\u4EE3\\u7801\\u53EF\\u8BFB\\u6027\\u548C\\u53EF\\u7EF4\\u62A4\\u6027\\u3002\"]}),`\n`,(0,e.jsxs)(n.li,{children:[(0,e.jsx)(n.strong,{children:\"\\u9AD8\\u6548\\u7684\\u4E8B\\u4EF6\\u5904\\u7406\\uFF1A\"}),\" \\u901A\\u8FC7\\u9644\\u52A0\\u66F4\\u5C11\\u7684\\u76D1\\u542C\\u5668\\uFF0C\\u6700\\u5927\\u9650\\u5EA6\\u5730\\u51CF\\u5C11\\u6027\\u80FD\\u5F00\\u9500\\u3002\"]}),`\n`,(0,e.jsxs)(n.li,{children:[(0,e.jsx)(n.strong,{children:\"\\u7075\\u6D3B\\u6027\\uFF1A\"}),\" \\u5141\\u8BB8\\u5904\\u7406\\u5B50\\u5143\\u7D20\\u4E0A\\u53D1\\u751F\\u7684\\u4E8B\\u4EF6\\uFF0C\\u800C\\u65E0\\u9700\\u76F4\\u63A5\\u5C06\\u76D1\\u542C\\u5668\\u9644\\u52A0\\u5230\\u5B83\\u4EEC\\u3002\"]}),`\n`]}),`\n`,(0,e.jsx)(n.h2,{children:\"\\u9677\\u9631\"}),`\n`,(0,e.jsxs)(n.ul,{children:[`\n`,(0,e.jsxs)(n.li,{children:[(0,e.jsx)(n.strong,{children:\"\\u610F\\u5916\\u7684\\u4E8B\\u4EF6\\u5904\\u7406\\uFF1A\"}),\" \\u8BF7\\u6CE8\\u610F\\uFF0C\\u7236\\u5143\\u7D20\\u53EF\\u80FD\\u4F1A\\u65E0\\u610F\\u4E2D\\u6355\\u83B7\\u5B50\\u5143\\u7D20\\u53D1\\u751F\\u7684\\u4E8B\\u4EF6\\u3002\\u4F7F\\u7528 \",(0,e.jsx)(n.code,{children:\"event.target\"}),\" \\u6765\\u8BC6\\u522B\\u89E6\\u53D1\\u4E8B\\u4EF6\\u7684\\u7279\\u5B9A\\u5143\\u7D20\\u3002\"]}),`\n`,(0,e.jsxs)(n.li,{children:[(0,e.jsx)(n.strong,{children:\"\\u4E8B\\u4EF6\\u987A\\u5E8F\\uFF1A\"}),\" \\u4E8B\\u4EF6\\u4EE5\\u7279\\u5B9A\\u987A\\u5E8F\\u5192\\u6CE1\\u3002\\u5982\\u679C\\u591A\\u4E2A\\u7236\\u5143\\u7D20\\u6709\\u4E8B\\u4EF6\\u76D1\\u542C\\u5668\\uFF0C\\u5B83\\u4EEC\\u7684\\u6267\\u884C\\u987A\\u5E8F\\u53D6\\u51B3\\u4E8E DOM \\u5C42\\u6B21\\u7ED3\\u6784\\u3002\"]}),`\n`,(0,e.jsxs)(n.li,{children:[(0,e.jsx)(n.strong,{children:\"\\u8FC7\\u5EA6\\u59D4\\u6258\\uFF1A\"}),\" \\u867D\\u7136\\u5C06\\u4E8B\\u4EF6\\u59D4\\u6258\\u7ED9\\u516C\\u5171\\u7956\\u5148\\u662F\\u6709\\u6548\\u7684\\uFF0C\\u4F46\\u5728 DOM \\u6811\\u4E2D\\u9644\\u52A0\\u4E00\\u4E2A\\u8FC7\\u9AD8\\u7684\\u76D1\\u542C\\u5668\\u53EF\\u80FD\\u4F1A\\u6355\\u83B7\\u610F\\u5916\\u7684\\u4E8B\\u4EF6\\u3002\"]}),`\n`]}),`\n`,(0,e.jsx)(n.h2,{children:\"\\u7528\\u4F8B\"}),`\n`,(0,e.jsx)(n.p,{children:\"\\u4EE5\\u4E0B\\u662F\\u4E00\\u4E9B\\u4F7F\\u7528\\u4E8B\\u4EF6\\u5192\\u6CE1\\u7F16\\u5199\\u66F4\\u597D\\u4EE3\\u7801\\u7684\\u5B9E\\u7528\\u65B9\\u6CD5\\u3002\"}),`\n`,(0,e.jsx)(n.h3,{children:\"\\u4F7F\\u7528\\u4E8B\\u4EF6\\u59D4\\u6258\\u51CF\\u5C11\\u4EE3\\u7801\"}),`\n`,(0,e.jsx)(n.p,{children:\"\\u60F3\\u8C61\\u4E00\\u4E0B\\uFF0C\\u60A8\\u6709\\u4E00\\u4E2A\\u4EA7\\u54C1\\u5217\\u8868\\uFF0C\\u5176\\u4E2D\\u5305\\u542B\\u8BB8\\u591A\\u9879\\u76EE\\uFF0C\\u6BCF\\u4E2A\\u9879\\u76EE\\u90FD\\u6709\\u4E00\\u4E2A\\u201C\\u7ACB\\u5373\\u8D2D\\u4E70\\u201D\\u6309\\u94AE\\u3002 \\u4F20\\u7EDF\\u4E0A\\uFF0C\\u60A8\\u53EF\\u4EE5\\u5C06\\u5355\\u72EC\\u7684\\u70B9\\u51FB\\u4E8B\\u4EF6\\u76D1\\u542C\\u5668\\u9644\\u52A0\\u5230\\u6BCF\\u4E2A\\u6309\\u94AE\\uFF1A\"}),`\n`,(0,e.jsx)(n.pre,{children:(0,e.jsx)(n.code,{className:\"language-js\",children:`// HTML:\n// \n\nconst item1Buy = document.getElementById('item1-buy');\nconst item2Buy = document.getElementById('item2-buy');\n\nitem1Buy.addEventListener('click', handleBuyClick);\nitem2Buy.addEventListener('click', handleBuyClick);\n\n// ... \\u5BF9\\u6BCF\\u4E2A\\u9879\\u76EE\\u91CD\\u590D ...\n\nfunction handleBuyClick(event) {\n console.log('\\u70B9\\u51FB\\u4E86\\u9879\\u76EE\\u7684\\u8D2D\\u4E70\\u6309\\u94AE\\uFF1A', event.target.id);\n}\n`})}),`\n`,(0,e.jsx)(n.p,{children:\"\\u968F\\u7740\\u9879\\u76EE\\u6570\\u91CF\\u7684\\u589E\\u52A0\\uFF0C\\u8FD9\\u79CD\\u65B9\\u6CD5\\u53D8\\u5F97\\u5F88\\u9EBB\\u70E6\\u3002 \\u4EE5\\u4E0B\\u662F\\u4E8B\\u4EF6\\u5192\\u6CE1\\u5982\\u4F55\\u7B80\\u5316\\u4E8B\\u60C5\\u7684\\u65B9\\u6CD5\\uFF1A\"}),`\n`,(0,e.jsx)(n.pre,{children:(0,e.jsx)(n.code,{className:\"language-js\",children:`// HTML:\n// \n\nconst productList = document.getElementById('product-list');\n\nproductList.addEventListener('click', handleBuyClick);\n\nfunction handleBuyClick(event) {\n // \\u68C0\\u67E5\\u70B9\\u51FB\\u7684\\u5143\\u7D20\\u662F\\u5426\\u662F\\u5217\\u8868\\u4E2D\\u7684\\u4E00\\u4E2A\\u6309\\u94AE\n if (event.target.tagName.toLowerCase() === 'button') {\n console.log('\\u70B9\\u51FB\\u4E86\\u9879\\u76EE\\u7684\\u8D2D\\u4E70\\u6309\\u94AE\\uFF1A', event.target.textContent);\n }\n}\n`})}),`\n`,(0,e.jsxs)(n.p,{children:[\"\\u901A\\u8FC7\\u5C06\\u76D1\\u542C\\u5668\\u9644\\u52A0\\u5230\\u7236\\u5143\\u7D20 (\",(0,e.jsx)(n.code,{children:\"productList\"}),\") \\u5E76\\u5728\\u5904\\u7406\\u7A0B\\u5E8F\\u4E2D\\u68C0\\u67E5\\u88AB\\u70B9\\u51FB\\u7684\\u5143\\u7D20 (\",(0,e.jsx)(n.code,{children:\"event.target\"}),\")\\uFF0C\\u60A8\\u53EF\\u4EE5\\u7528\\u66F4\\u5C11\\u7684\\u4EE3\\u7801\\u5B9E\\u73B0\\u76F8\\u540C\\u7684\\u529F\\u80FD\\u3002 \\u5F53\\u9879\\u76EE\\u662F\\u52A8\\u6001\\u7684\\u65F6\\uFF0C\\u8FD9\\u79CD\\u65B9\\u6CD5\\u53EF\\u4EE5\\u5F88\\u597D\\u5730\\u6269\\u5C55\\uFF0C\\u56E0\\u4E3A\\u5F53\\u9879\\u76EE\\u5217\\u8868\\u53D1\\u751F\\u53D8\\u5316\\u65F6\\uFF0C\\u4E0D\\u9700\\u8981\\u6DFB\\u52A0\\u6216\\u5220\\u9664\\u65B0\\u7684\\u4E8B\\u4EF6\\u5904\\u7406\\u7A0B\\u5E8F\\u3002\"]}),`\n`,(0,e.jsx)(n.h3,{children:\"\\u4E0B\\u62C9\\u83DC\\u5355\"}),`\n`,(0,e.jsx)(n.p,{children:\"\\u8003\\u8651\\u4E00\\u4E2A\\u4E0B\\u62C9\\u83DC\\u5355\\uFF0C\\u70B9\\u51FB\\u83DC\\u5355\\u5143\\u7D20\\uFF08\\u7236\\u5143\\u7D20\\uFF09\\u7684\\u4EFB\\u4F55\\u5730\\u65B9\\u90FD\\u5E94\\u8BE5\\u5173\\u95ED\\u5B83\\u3002\\u4F7F\\u7528\\u4E8B\\u4EF6\\u5192\\u6CE1\\uFF0C\\u60A8\\u53EF\\u4EE5\\u4F7F\\u7528\\u4E00\\u4E2A\\u76D1\\u542C\\u5668\\u6765\\u5B9E\\u73B0\\u8FD9\\u4E00\\u70B9\\uFF1A\"}),`\n`,(0,e.jsx)(n.pre,{children:(0,e.jsx)(n.code,{className:\"language-js\",children:`// HTML:\n//
\n// \n// \n//
\n\nconst dropdown = document.getElementById('dropdown');\n\ndropdown.addEventListener('click', handleDropdownClick);\n\nfunction handleDropdownClick(event) {\n // \\u5982\\u679C\\u5728\\u6309\\u94AE\\u5916\\u90E8\\u5355\\u51FB\\uFF0C\\u5219\\u5173\\u95ED\\u4E0B\\u62C9\\u83DC\\u5355\n if (event.target !== dropdown.querySelector('button')) {\n console.log('\\u4E0B\\u62C9\\u83DC\\u5355\\u5DF2\\u5173\\u95ED');\n // \\u9690\\u85CF\\u4E0B\\u62C9\\u83DC\\u5355\\u5185\\u5BB9\\u7684\\u903B\\u8F91\n }\n}\n`})}),`\n`,(0,e.jsxs)(n.p,{children:[\"\\u5728\\u8FD9\\u91CC\\uFF0C\\u70B9\\u51FB\\u4E8B\\u4EF6\\u4ECE\\u88AB\\u70B9\\u51FB\\u7684\\u5143\\u7D20\\uFF08\\u6309\\u94AE\\u6216\\u5217\\u8868\\u9879\\uFF09\\u5192\\u6CE1\\u5230 \",(0,e.jsx)(n.code,{children:\"dropdown\"}),\" \\u5143\\u7D20\\u3002 \\u5904\\u7406\\u7A0B\\u5E8F\\u68C0\\u67E5\\u88AB\\u70B9\\u51FB\\u7684\\u5143\\u7D20\\u662F\\u5426\\u4E0D\\u662F \",(0,e.jsx)(n.code,{children:\"\n// \nconst parentDiv = document.createElement('div');\nparentDiv.id = 'parent';\nconst button = document.createElement('button');\nbutton.id = 'child';\nparentDiv.appendChild(button);\ndocument.body.appendChild(parentDiv);\n\nconst parent = document.getElementById('parent');\nconst child = document.getElementById('child');\n\nparent.addEventListener('click', () => {\n console.log('Parent element clicked');\n});\n\nchild.addEventListener('click', () => {\n console.log('Child element clicked');\n});\n\n// Simulate clicking the button:\nchild.click();\n`})}),`\n`,(0,e.jsx)(n.p,{children:\"\\u5F53\\u60A8\\u70B9\\u51FB\\u201CClick me!\\u201D\\u6309\\u94AE\\u65F6\\uFF0C\\u7531\\u4E8E\\u4E8B\\u4EF6\\u5192\\u6CE1\\uFF0C\\u5B50\\u5143\\u7D20\\u548C\\u7236\\u5143\\u7D20\\u7684\\u4E8B\\u4EF6\\u5904\\u7406\\u7A0B\\u5E8F\\u90FD\\u5C06\\u88AB\\u89E6\\u53D1\\u3002\"}),`\n`,(0,e.jsx)(n.h2,{children:\"\\u505C\\u6B62\\u5192\\u6CE1\"}),`\n`,(0,e.jsxs)(n.p,{children:[\"\\u53EF\\u4EE5\\u4F7F\\u7528 \",(0,e.jsx)(n.code,{children:\"stopPropagation()\"}),\" \\u65B9\\u6CD5\\u5728\\u5192\\u6CE1\\u9636\\u6BB5\\u505C\\u6B62\\u4E8B\\u4EF6\\u5192\\u6CE1\\u3002\\u5982\\u679C\\u4E8B\\u4EF6\\u5904\\u7406\\u7A0B\\u5E8F\\u8C03\\u7528 \",(0,e.jsx)(n.code,{children:\"stopPropagation()\"}),\"\\uFF0C\\u5B83\\u4F1A\\u963B\\u6B62\\u4E8B\\u4EF6\\u8FDB\\u4E00\\u6B65\\u5192\\u6CE1\\u5230 DOM \\u6811\\u4E2D\\uFF0C\\u786E\\u4FDD\\u4EC5\\u6267\\u884C\\u5C42\\u6B21\\u7ED3\\u6784\\u4E2D\\u8BE5\\u70B9\\u4E4B\\u524D\\u7684\\u5143\\u7D20\\u7684\\u5904\\u7406\\u7A0B\\u5E8F\\u3002\"]}),`\n`,(0,e.jsx)(n.pre,{live:!0,children:(0,e.jsx)(n.code,{className:\"language-js\",children:`// HTML:\n//
\n// \n//
\nconst parentDiv = document.createElement('div');\nparentDiv.id = 'parent';\nconst button = document.createElement('button');\nbutton.id = 'child';\nparentDiv.appendChild(button);\ndocument.body.appendChild(parentDiv);\n\nconst parent = document.getElementById('parent');\nconst child = document.getElementById('child');\n\nparent.addEventListener('click', () => {\n console.log('Parent element clicked');\n});\n\nchild.addEventListener('click', (event) => {\n console.log('Child element clicked');\n event.stopPropagation(); // Stops propagation to parent\n});\n\n// Simulate clicking the button:\nchild.click();\n`})}),`\n`,(0,e.jsx)(n.h2,{children:\"\\u4E8B\\u4EF6\\u59D4\\u6258\"}),`\n`,(0,e.jsxs)(n.p,{children:[\"\\u4E8B\\u4EF6\\u5192\\u6CE1\\u662F\",(0,e.jsx)(n.a,{href:\"/questions/quiz/explain-event-delegation\",children:\"\\u4E8B\\u4EF6\\u59D4\\u6258\"}),\"\\u6280\\u672F\\u7684\\u57FA\\u7840\\uFF0C\\u60A8\\u53EF\\u4EE5\\u5728\\u591A\\u4E2A\\u5143\\u7D20\\u7684\\u516C\\u5171\\u7956\\u5148\\u4E0A\\u9644\\u52A0\\u5355\\u4E2A\\u4E8B\\u4EF6\\u5904\\u7406\\u7A0B\\u5E8F\\uFF0C\\u5E76\\u4F7F\\u7528\\u4E8B\\u4EF6\\u59D4\\u6258\\u6765\\u6709\\u6548\\u5730\\u5904\\u7406\\u8FD9\\u4E9B\\u5143\\u7D20\\u7684\\u4E8B\\u4EF6\\u3002\\u5F53\\u60A8\\u6709\\u5927\\u91CF\\u76F8\\u4F3C\\u7684\\u5143\\u7D20\\uFF08\\u5982\\u9879\\u76EE\\u5217\\u8868\\uFF09\\u5E76\\u4E14\\u5E0C\\u671B\\u907F\\u514D\\u5C06\\u5355\\u72EC\\u7684\\u4E8B\\u4EF6\\u5904\\u7406\\u7A0B\\u5E8F\\u9644\\u52A0\\u5230\\u6BCF\\u4E2A\\u9879\\u76EE\\u65F6\\uFF0C\\u8FD9\\u7279\\u522B\\u6709\\u7528\\u3002\"]}),`\n`,(0,e.jsx)(n.pre,{children:(0,e.jsx)(n.code,{className:\"language-js\",children:`parent.addEventListener('click', (event) => {\n if (event.target && event.target.id === 'child') {\n console.log('Child element clicked');\n }\n});\n`})}),`\n`,(0,e.jsx)(n.h2,{children:\"\\u4F18\\u70B9\"}),`\n`,(0,e.jsxs)(n.ul,{children:[`\n`,(0,e.jsxs)(n.li,{children:[(0,e.jsx)(n.strong,{children:\"\\u66F4\\u7B80\\u6D01\\u7684\\u4EE3\\u7801\\uFF1A\"}),\" \\u51CF\\u5C11\\u4E8B\\u4EF6\\u76D1\\u542C\\u5668\\u7684\\u6570\\u91CF\\uFF0C\\u63D0\\u9AD8\\u4EE3\\u7801\\u53EF\\u8BFB\\u6027\\u548C\\u53EF\\u7EF4\\u62A4\\u6027\\u3002\"]}),`\n`,(0,e.jsxs)(n.li,{children:[(0,e.jsx)(n.strong,{children:\"\\u9AD8\\u6548\\u7684\\u4E8B\\u4EF6\\u5904\\u7406\\uFF1A\"}),\" \\u901A\\u8FC7\\u9644\\u52A0\\u66F4\\u5C11\\u7684\\u76D1\\u542C\\u5668\\uFF0C\\u6700\\u5927\\u9650\\u5EA6\\u5730\\u51CF\\u5C11\\u6027\\u80FD\\u5F00\\u9500\\u3002\"]}),`\n`,(0,e.jsxs)(n.li,{children:[(0,e.jsx)(n.strong,{children:\"\\u7075\\u6D3B\\u6027\\uFF1A\"}),\" \\u5141\\u8BB8\\u5904\\u7406\\u5B50\\u5143\\u7D20\\u4E0A\\u53D1\\u751F\\u7684\\u4E8B\\u4EF6\\uFF0C\\u800C\\u65E0\\u9700\\u76F4\\u63A5\\u5C06\\u76D1\\u542C\\u5668\\u9644\\u52A0\\u5230\\u5B83\\u4EEC\\u3002\"]}),`\n`]}),`\n`,(0,e.jsx)(n.h2,{children:\"\\u9677\\u9631\"}),`\n`,(0,e.jsxs)(n.ul,{children:[`\n`,(0,e.jsxs)(n.li,{children:[(0,e.jsx)(n.strong,{children:\"\\u610F\\u5916\\u7684\\u4E8B\\u4EF6\\u5904\\u7406\\uFF1A\"}),\" \\u8BF7\\u6CE8\\u610F\\uFF0C\\u7236\\u5143\\u7D20\\u53EF\\u80FD\\u4F1A\\u65E0\\u610F\\u4E2D\\u6355\\u83B7\\u5B50\\u5143\\u7D20\\u53D1\\u751F\\u7684\\u4E8B\\u4EF6\\u3002\\u4F7F\\u7528 \",(0,e.jsx)(n.code,{children:\"event.target\"}),\" \\u6765\\u8BC6\\u522B\\u89E6\\u53D1\\u4E8B\\u4EF6\\u7684\\u7279\\u5B9A\\u5143\\u7D20\\u3002\"]}),`\n`,(0,e.jsxs)(n.li,{children:[(0,e.jsx)(n.strong,{children:\"\\u4E8B\\u4EF6\\u987A\\u5E8F\\uFF1A\"}),\" \\u4E8B\\u4EF6\\u4EE5\\u7279\\u5B9A\\u987A\\u5E8F\\u5192\\u6CE1\\u3002\\u5982\\u679C\\u591A\\u4E2A\\u7236\\u5143\\u7D20\\u6709\\u4E8B\\u4EF6\\u76D1\\u542C\\u5668\\uFF0C\\u5B83\\u4EEC\\u7684\\u6267\\u884C\\u987A\\u5E8F\\u53D6\\u51B3\\u4E8E DOM \\u5C42\\u6B21\\u7ED3\\u6784\\u3002\"]}),`\n`,(0,e.jsxs)(n.li,{children:[(0,e.jsx)(n.strong,{children:\"\\u8FC7\\u5EA6\\u59D4\\u6258\\uFF1A\"}),\" \\u867D\\u7136\\u5C06\\u4E8B\\u4EF6\\u59D4\\u6258\\u7ED9\\u516C\\u5171\\u7956\\u5148\\u662F\\u6709\\u6548\\u7684\\uFF0C\\u4F46\\u5728 DOM \\u6811\\u4E2D\\u9644\\u52A0\\u4E00\\u4E2A\\u8FC7\\u9AD8\\u7684\\u76D1\\u542C\\u5668\\u53EF\\u80FD\\u4F1A\\u6355\\u83B7\\u610F\\u5916\\u7684\\u4E8B\\u4EF6\\u3002\"]}),`\n`]}),`\n`,(0,e.jsx)(n.h2,{children:\"\\u7528\\u4F8B\"}),`\n`,(0,e.jsx)(n.p,{children:\"\\u4EE5\\u4E0B\\u662F\\u4E00\\u4E9B\\u4F7F\\u7528\\u4E8B\\u4EF6\\u5192\\u6CE1\\u7F16\\u5199\\u66F4\\u597D\\u4EE3\\u7801\\u7684\\u5B9E\\u7528\\u65B9\\u6CD5\\u3002\"}),`\n`,(0,e.jsx)(n.h3,{children:\"\\u4F7F\\u7528\\u4E8B\\u4EF6\\u59D4\\u6258\\u51CF\\u5C11\\u4EE3\\u7801\"}),`\n`,(0,e.jsx)(n.p,{children:\"\\u60F3\\u8C61\\u4E00\\u4E0B\\uFF0C\\u60A8\\u6709\\u4E00\\u4E2A\\u4EA7\\u54C1\\u5217\\u8868\\uFF0C\\u5176\\u4E2D\\u5305\\u542B\\u8BB8\\u591A\\u9879\\u76EE\\uFF0C\\u6BCF\\u4E2A\\u9879\\u76EE\\u90FD\\u6709\\u4E00\\u4E2A\\u201C\\u7ACB\\u5373\\u8D2D\\u4E70\\u201D\\u6309\\u94AE\\u3002 \\u4F20\\u7EDF\\u4E0A\\uFF0C\\u60A8\\u53EF\\u4EE5\\u5C06\\u5355\\u72EC\\u7684\\u70B9\\u51FB\\u4E8B\\u4EF6\\u76D1\\u542C\\u5668\\u9644\\u52A0\\u5230\\u6BCF\\u4E2A\\u6309\\u94AE\\uFF1A\"}),`\n`,(0,e.jsx)(n.pre,{children:(0,e.jsx)(n.code,{className:\"language-js\",children:`// HTML:\n// \n\nconst item1Buy = document.getElementById('item1-buy');\nconst item2Buy = document.getElementById('item2-buy');\n\nitem1Buy.addEventListener('click', handleBuyClick);\nitem2Buy.addEventListener('click', handleBuyClick);\n\n// ... \\u5BF9\\u6BCF\\u4E2A\\u9879\\u76EE\\u91CD\\u590D ...\n\nfunction handleBuyClick(event) {\n console.log('\\u70B9\\u51FB\\u4E86\\u9879\\u76EE\\u7684\\u8D2D\\u4E70\\u6309\\u94AE\\uFF1A', event.target.id);\n}\n`})}),`\n`,(0,e.jsx)(n.p,{children:\"\\u968F\\u7740\\u9879\\u76EE\\u6570\\u91CF\\u7684\\u589E\\u52A0\\uFF0C\\u8FD9\\u79CD\\u65B9\\u6CD5\\u53D8\\u5F97\\u5F88\\u9EBB\\u70E6\\u3002 \\u4EE5\\u4E0B\\u662F\\u4E8B\\u4EF6\\u5192\\u6CE1\\u5982\\u4F55\\u7B80\\u5316\\u4E8B\\u60C5\\u7684\\u65B9\\u6CD5\\uFF1A\"}),`\n`,(0,e.jsx)(n.pre,{children:(0,e.jsx)(n.code,{className:\"language-js\",children:`// HTML:\n// \n\nconst productList = document.getElementById('product-list');\n\nproductList.addEventListener('click', handleBuyClick);\n\nfunction handleBuyClick(event) {\n // \\u68C0\\u67E5\\u70B9\\u51FB\\u7684\\u5143\\u7D20\\u662F\\u5426\\u662F\\u5217\\u8868\\u4E2D\\u7684\\u4E00\\u4E2A\\u6309\\u94AE\n if (event.target.tagName.toLowerCase() === 'button') {\n console.log('\\u70B9\\u51FB\\u4E86\\u9879\\u76EE\\u7684\\u8D2D\\u4E70\\u6309\\u94AE\\uFF1A', event.target.textContent);\n }\n}\n`})}),`\n`,(0,e.jsxs)(n.p,{children:[\"\\u901A\\u8FC7\\u5C06\\u76D1\\u542C\\u5668\\u9644\\u52A0\\u5230\\u7236\\u5143\\u7D20 (\",(0,e.jsx)(n.code,{children:\"productList\"}),\") \\u5E76\\u5728\\u5904\\u7406\\u7A0B\\u5E8F\\u4E2D\\u68C0\\u67E5\\u88AB\\u70B9\\u51FB\\u7684\\u5143\\u7D20 (\",(0,e.jsx)(n.code,{children:\"event.target\"}),\")\\uFF0C\\u60A8\\u53EF\\u4EE5\\u7528\\u66F4\\u5C11\\u7684\\u4EE3\\u7801\\u5B9E\\u73B0\\u76F8\\u540C\\u7684\\u529F\\u80FD\\u3002 \\u5F53\\u9879\\u76EE\\u662F\\u52A8\\u6001\\u7684\\u65F6\\uFF0C\\u8FD9\\u79CD\\u65B9\\u6CD5\\u53EF\\u4EE5\\u5F88\\u597D\\u5730\\u6269\\u5C55\\uFF0C\\u56E0\\u4E3A\\u5F53\\u9879\\u76EE\\u5217\\u8868\\u53D1\\u751F\\u53D8\\u5316\\u65F6\\uFF0C\\u4E0D\\u9700\\u8981\\u6DFB\\u52A0\\u6216\\u5220\\u9664\\u65B0\\u7684\\u4E8B\\u4EF6\\u5904\\u7406\\u7A0B\\u5E8F\\u3002\"]}),`\n`,(0,e.jsx)(n.h3,{children:\"\\u4E0B\\u62C9\\u83DC\\u5355\"}),`\n`,(0,e.jsx)(n.p,{children:\"\\u8003\\u8651\\u4E00\\u4E2A\\u4E0B\\u62C9\\u83DC\\u5355\\uFF0C\\u70B9\\u51FB\\u83DC\\u5355\\u5143\\u7D20\\uFF08\\u7236\\u5143\\u7D20\\uFF09\\u7684\\u4EFB\\u4F55\\u5730\\u65B9\\u90FD\\u5E94\\u8BE5\\u5173\\u95ED\\u5B83\\u3002\\u4F7F\\u7528\\u4E8B\\u4EF6\\u5192\\u6CE1\\uFF0C\\u60A8\\u53EF\\u4EE5\\u4F7F\\u7528\\u4E00\\u4E2A\\u76D1\\u542C\\u5668\\u6765\\u5B9E\\u73B0\\u8FD9\\u4E00\\u70B9\\uFF1A\"}),`\n`,(0,e.jsx)(n.pre,{children:(0,e.jsx)(n.code,{className:\"language-js\",children:`// HTML:\n//
\n// \n// \n//
\n\nconst dropdown = document.getElementById('dropdown');\n\ndropdown.addEventListener('click', handleDropdownClick);\n\nfunction handleDropdownClick(event) {\n // \\u5982\\u679C\\u5728\\u6309\\u94AE\\u5916\\u90E8\\u5355\\u51FB\\uFF0C\\u5219\\u5173\\u95ED\\u4E0B\\u62C9\\u83DC\\u5355\n if (event.target !== dropdown.querySelector('button')) {\n console.log('\\u4E0B\\u62C9\\u83DC\\u5355\\u5DF2\\u5173\\u95ED');\n // \\u9690\\u85CF\\u4E0B\\u62C9\\u83DC\\u5355\\u5185\\u5BB9\\u7684\\u903B\\u8F91\n }\n}\n`})}),`\n`,(0,e.jsxs)(n.p,{children:[\"\\u5728\\u8FD9\\u91CC\\uFF0C\\u70B9\\u51FB\\u4E8B\\u4EF6\\u4ECE\\u88AB\\u70B9\\u51FB\\u7684\\u5143\\u7D20\\uFF08\\u6309\\u94AE\\u6216\\u5217\\u8868\\u9879\\uFF09\\u5192\\u6CE1\\u5230 \",(0,e.jsx)(n.code,{children:\"dropdown\"}),\" \\u5143\\u7D20\\u3002 \\u5904\\u7406\\u7A0B\\u5E8F\\u68C0\\u67E5\\u88AB\\u70B9\\u51FB\\u7684\\u5143\\u7D20\\u662F\\u5426\\u4E0D\\u662F \",(0,e.jsx)(n.code,{children:\"\n// \n// \n// \n\nconst buttonContainer = document.getElementById('button-container');\nconst addButton = document.getElementById('add-button');\n\nbuttonContainer.addEventListener('click', (event) => {\n if (event.target.tagName === 'BUTTON') {\n console.log(\\`Clicked on \\${event.target.textContent}\\`);\n }\n});\n\naddButton.addEventListener('click', () => {\n const newButton = document.createElement('button');\n newButton.textContent = \\`Button \\${buttonContainer.children.length + 1}\\`;\n buttonContainer.appendChild(newButton);\n});\n`})}),`\n`,(0,n.jsxs)(e.p,{children:[\"In this example, a \",(0,n.jsx)(e.code,{children:\"click\"}),\" event listener is attached to the \",(0,n.jsx)(e.code,{children:\"
\"}),\" container. When a new button is added dynamically and clicked, the event listener on the container handles the click event.\"]}),`\n`,(0,n.jsx)(e.h3,{children:\"Simplifying code by avoiding the need to attach and remove event listeners for elements that change\"}),`\n`,(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:\"language-js\",children:`// HTML:\n//
\n// \n// \n// \n//
\n\nconst userForm = document.getElementById('user-form');\n\nuserForm.addEventListener('input', (event) => {\n const { name, value } = event.target;\n console.log(\\`Changed \\${name}: \\${value}\\`);\n});\n`})}),`\n`,(0,n.jsxs)(e.p,{children:[\"In this example, a single input event listener is attached to the form element. It can respond to input changes for all child input elements, simplifying the code by an event listeners per \",(0,n.jsx)(e.code,{children:\"\"}),\" element.\"]}),`\n`,(0,n.jsx)(e.h2,{children:\"Pitfalls\"}),`\n`,(0,n.jsx)(e.p,{children:\"Do note that event delegation come with certain pitfalls:\"}),`\n`,(0,n.jsxs)(e.ul,{children:[`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Incorrect target handling:\"}),\" Ensure correct identification of the event target to avoid unintended actions.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Not all events can be delegated/bubbled\"}),\": Not all events can be delegated because they are not bubbled. Non-bubbling events include: \",(0,n.jsx)(e.code,{children:\"focus\"}),\", \",(0,n.jsx)(e.code,{children:\"blur\"}),\", \",(0,n.jsx)(e.code,{children:\"scroll\"}),\", \",(0,n.jsx)(e.code,{children:\"mouseenter\"}),\", \",(0,n.jsx)(e.code,{children:\"mouseleave\"}),\", \",(0,n.jsx)(e.code,{children:\"resize\"}),\", etc.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Event overhead:\"}),\" While event delegation is generally more efficient, there needs to be complex logic written within the root event listener to identify the triggering element and respond appropriately. This can introduce overhead and can be potentially more complex if not managed properly.\"]}),`\n`]}),`\n`,(0,n.jsx)(e.h2,{children:\"Event delegation in JavaScript frameworks\"}),`\n`,(0,n.jsxs)(e.p,{children:[\"In \",(0,n.jsx)(e.a,{href:\"https://react.dev/\",children:\"React\"}),\", event handlers are attached to the React root's DOM container into which the React tree is rendered. Even though \",(0,n.jsx)(e.code,{children:\"onClick\"}),\" is added to child elements, the actual event listeners are attached to the root DOM node, leveraging event delegation to optimize event handling and improve performance.\"]}),`\n`,(0,n.jsx)(e.p,{children:\"When an event occurs, React's event listener captures it and determines which React component rendered the target element based on its internal bookkeeping. React then dispatches the event to the appropriate component's event handler by calling the handler function with a synthetic event object. This synthetic event object wraps the native browser event, providing a consistent interface across different browsers and capturing information about the event.\"}),`\n`,(0,n.jsx)(e.p,{children:\"By using event delegation, React avoids attaching individual event handlers to each component instance, which would create significant overhead, especially for large component trees. Instead, React leverages the browser's native event bubbling mechanism to capture events at the root and distribute them to the appropriate components.\"}),`\n`,(0,n.jsx)(e.h2,{children:\"Further reading\"}),`\n`,(0,n.jsxs)(e.ul,{children:[`\n`,(0,n.jsx)(e.li,{children:(0,n.jsx)(e.a,{href:\"https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_delegation\",children:\"MDN Web Docs on Event Delegation\"})}),`\n`,(0,n.jsx)(e.li,{children:(0,n.jsx)(e.a,{href:\"https://javascript.info/event-delegation\",children:\"JavaScript.info - Event Delegation\"})}),`\n`,(0,n.jsx)(e.li,{children:(0,n.jsx)(e.a,{href:\"https://legacy.reactjs.org/blog/2020/08/10/react-v17-rc.html#changes-to-event-delegation\",children:\"React v17.0 Release Candidate: No New Features\"})}),`\n`]})]})}function E(t={}){let{wrapper:e}=t.components||{};return e?(0,n.jsx)(e,Object.assign({},t,{children:(0,n.jsx)(h,t)})):h(t)}var k=E;return y(x);})();\n;return Component;" + "solution": "var Component=(()=>{var s=Object.create;var a=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var g=Object.getPrototypeOf,v=Object.prototype.hasOwnProperty;var p=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),b=(t,e)=>{for(var i in e)a(t,i,{get:e[i],enumerable:!0})},o=(t,e,i,r)=>{if(e&&typeof e==\"object\"||typeof e==\"function\")for(let l of u(e))!v.call(t,l)&&l!==i&&a(t,l,{get:()=>e[l],enumerable:!(r=m(e,l))||r.enumerable});return t};var f=(t,e,i)=>(i=t!=null?s(g(t)):{},o(e||!t||!t.__esModule?a(i,\"default\",{value:t,enumerable:!0}):i,t)),y=t=>o(a({},\"__esModule\",{value:!0}),t);var d=p((D,c)=>{c.exports=_jsx_runtime});var x={};b(x,{default:()=>k,frontmatter:()=>w});var n=f(d()),w={title:\"Explain event delegation in JavaScript\"};function h(t){let e=Object.assign({h2:\"h2\",p:\"p\",ul:\"ul\",li:\"li\",strong:\"strong\",code:\"code\",hr:\"hr\",ol:\"ol\",pre:\"pre\",h3:\"h3\",a:\"a\"},t.components);return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.h2,{children:\"TL;DR\"}),`\n`,(0,n.jsx)(e.p,{children:\"Event delegation is a technique in JavaScript where a single event listener is attached to a parent element instead of attaching event listeners to multiple child elements. When an event occurs on a child element, the event bubbles up the DOM tree, and the parent element's event listener handles the event based on the target element.\"}),`\n`,(0,n.jsx)(e.p,{children:\"Event delegation provides the following benefits:\"}),`\n`,(0,n.jsxs)(e.ul,{children:[`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Improved performance\"}),\": Attaching a single event listener is more efficient than attaching multiple event listeners to individual elements, especially for large or dynamic lists. This reduces memory usage and improves overall performance.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Simplified event handling\"}),\": With event delegation, you only need to write the event handling logic once in the parent element's event listener. This makes the code more maintainable and easier to update.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Dynamic element support\"}),\": Event delegation automatically handles events for dynamically added or removed elements within the parent element. There's no need to manually attach or remove event listeners when the DOM structure changes\"]}),`\n`]}),`\n`,(0,n.jsx)(e.p,{children:\"However, do note that:\"}),`\n`,(0,n.jsxs)(e.ul,{children:[`\n`,(0,n.jsx)(e.li,{children:\"It is important to identify the target element that triggered the event.\"}),`\n`,(0,n.jsxs)(e.li,{children:[\"Not all events can be delegated because they are not bubbled. Non-bubbling events include: \",(0,n.jsx)(e.code,{children:\"focus\"}),\", \",(0,n.jsx)(e.code,{children:\"blur\"}),\", \",(0,n.jsx)(e.code,{children:\"scroll\"}),\", \",(0,n.jsx)(e.code,{children:\"mouseenter\"}),\", \",(0,n.jsx)(e.code,{children:\"mouseleave\"}),\", \",(0,n.jsx)(e.code,{children:\"resize\"}),\", etc.\"]}),`\n`]}),`\n`,(0,n.jsx)(e.hr,{}),`\n`,(0,n.jsx)(e.h2,{children:\"Event delegation\"}),`\n`,(0,n.jsx)(e.p,{children:\"Event delegation is a design pattern in JavaScript used to efficiently manage and handle events on multiple child elements by attaching a single event listener to a common ancestor element. This pattern is particularly valuable in scenarios where you have a large number of similar elements, such as list items, and want to optimize event handling.\"}),`\n`,(0,n.jsx)(e.h2,{children:\"How event delegation works\"}),`\n`,(0,n.jsxs)(e.ol,{children:[`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Attach a listener to a common ancestor\"}),\": Instead of attaching individual event listeners to each child element, you attach a single event listener to a common ancestor element higher in the DOM hierarchy.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Event bubbling\"}),\": When an event occurs on a child element, it bubbles up through the DOM tree to the common ancestor element. During this propagation, the event listener on the common ancestor can intercept and handle the event.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Determine the target\"}),\": Within the event listener, you can inspect the event object to identify the actual target of the event (the child element that triggered the event). You can use properties like \",(0,n.jsx)(e.code,{children:\"event.target\"}),\" or \",(0,n.jsx)(e.code,{children:\"event.currentTarget\"}),\" to determine which specific child element was interacted with.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Perform action based on target\"}),\": Based on the target element, you can perform the desired action or execute code specific to that element. This allows you to handle events for multiple child elements with a single event listener.\"]}),`\n`]}),`\n`,(0,n.jsx)(e.h2,{children:\"Benefits of event delegation\"}),`\n`,(0,n.jsxs)(e.ol,{children:[`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Efficiency\"}),\": Event delegation reduces the number of event listeners, improving memory usage and performance, especially when dealing with a large number of elements.\"]}),`\n`,(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:\"Dynamic elements\"}),\": It works seamlessly with dynamically added or removed child elements, as the common ancestor continues to listen for events on them.\"]}),`\n`]}),`\n`,(0,n.jsx)(e.h2,{children:\"Example\"}),`\n`,(0,n.jsx)(e.p,{children:\"Here's a simple example:\"}),`\n`,(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:\"language-js\",children:`// HTML:\n// \n\nconst itemList = document.getElementById('item-list');\n\nitemList.addEventListener('click', (event) => {\n if (event.target.tagName === 'LI') {\n console.log(\\`Clicked on \\${event.target.textContent}\\`);\n }\n});\n`})}),`\n`,(0,n.jsxs)(e.p,{children:[\"In this example, a single click event listener is attached to the \",(0,n.jsx)(e.code,{children:\"