๋ฐ˜์‘ํ˜•

์‹ค์Šต์šฉ CodePen


์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง/์บก์ฒ˜๋ง, `stopPropagation()`, `preventDefault()`๊นŒ์ง€ ๋ชจ๋‘ ์‹ค์Šตํ•  ์ˆ˜ ์žˆ๋„๋ก ์ž‘์„ฑ

 

See the Pen Learn Event Propagation ์ด๋ฒคํŠธ ์ „ํŒŒ ์‹ค์Šต by ColorFilter (@colorfilter) on CodePen.

 

 

์ด๋ฒคํŠธ ์ „ํŒŒ | Event Propagation


๋ฒ„๋ธ”๋ง Bubbling / ์บก์ฒ˜๋ง Capturing

์œ„ ์ฝ”๋“œํŽœ ์˜ˆ์ œ์—์„œ ํ•˜๋‹จ์— ์žˆ๋Š” span ํƒœ๊ทธ๋ฅผ ํด๋ฆญํ•˜๋ฉด โžŠ "span ์˜์—ญ" → โž‹ "p ์˜์—ญ" → โžŒ "div" ์˜์—ญ ์ˆœ์œผ๋กœ ์ฝ˜์†”์ด ์ฐํžŒ๋‹ค. span ์˜์—ญ์„ ํด๋ฆญํ•œ ์ˆœ๊ฐ„ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•ด์„œ ์ตœ์ƒ์œ„์— ์žˆ๋Š” ์š”์†Œ๊นŒ์ง€ ์ด๋ฒคํŠธ๊ฐ€ ์ „๋‹ฌ๋˜๋Š” ๊ฒƒ. ์ด๊ฒƒ์„ ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

 

์ด๋ฒคํŠธ ์บก์ฒ˜๋ง์€ ๋ฒ„๋ธ”๋ง ๋ฐ˜๋Œ€๋ฐฉํ–ฅ์œผ๋กœ ์ง„ํ–‰๋œ๋‹ค. addEventListener() 3๋ฒˆ์งธ ์ธ์ž์— true๋ฅผ ๋ช…์‹œํ•˜๋ฉด ๋œ๋‹ค. ์ด๋Š” { capture: true } ๋ฅผ ๋ช…์‹œํ•œ ๊ฒƒ๊ณผ ๊ฐ™๋‹ค. ๊ธฐ๋ณธ ๊ฐ’์€ { capture: false }๋‹ค.

 

ํ•˜๋‹จ์˜ span ํƒœ๊ทธ๋ฅผ ํด๋ฆญํ•˜๋ฉด ์ฝ˜์†”์— โžŠ "div ์˜์—ญ" → โž‹ "p ์˜์—ญ" → โžŒ "span" ์˜์—ญ ์ˆœ์œผ๋กœ ์ฝ˜์†”์ด ์ฐํžŒ๋‹ค. <span> ํƒœ๊ทธ๋ฅผ ํด๋ฆญํ•œ ์ˆœ๊ฐ„ ์ตœ์ƒ์œ„ ์š”์†Œ <html> ํƒœ๊ทธ๋ถ€ํ„ฐ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ <span> ํƒœ๊ทธ๊นŒ์ง€ ๋‚ด๋ ค๊ฐ€๋ฉฐ ํƒ์ƒ‰ํ•˜๊ธฐ ์‹œ์ž‘ํ•œ๋‹ค. ํƒ์ƒ‰ํ•˜๋Š” ๊ณผ์ •์—์„œ ์ค‘๊ฐ„์„ ๊ฑฐ์น˜๋Š” ์š”์†Œ์— ํ• ๋‹น๋œ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์‹คํ–‰๋ผ์„œ ์ฝ˜์†”์ด ์ฐํžˆ๋Š” ๊ฒƒ.

 

โถ ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง(Event Bubbling) : ์•„๋ž˜ → ์œ„

`target` (์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ์š”์†Œ) → `...` → `body` → `html`

 

โท ์ด๋ฒคํŠธ ์บก์ฒ˜๋ง(Event Capturing): ์œ„ → ์•„๋ž˜

`html` → `body` → `...` → `target` (์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ์š”์†Œ)

 

โธ `addEventListener()` 3๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์บก์ฒ˜๋ง ์—ฌ๋ถ€ ๊ฒฐ์ •

์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง : `{ capture: false }` ํ˜น์€ `false` ํ˜น์€ ์•„๋ฌด๊ฒƒ๋„ ์ž…๋ ฅํ•˜์ง€ ์•Š์•˜์„ ๋•Œ

// ์•„๋ž˜ 3๊ฐœ ๋™์ผ
addEventListener('click', handler); // 3๋ฒˆ์งธ ์ธ์ž์— ์•„๋ฌด๊ฒƒ๋„ ์ž…๋ ฅํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฒ„๋ธ”๋ง ๊ธฐ๋ณธ
addEventListener('click', handler, false);
addEventListener('click', handler, { capture: false });

 

์ด๋ฒคํŠธ ์บก์ฒ˜๋ง : `{ capture: true }` ํ˜น์€ `true`

// ์•„๋ž˜ 2๊ฐœ ๋™์ผ
addEventListener('click', handler, true);
addEventListener('click', handler, { capture: true });

 

๋ฆฌ์Šค๋„ˆ ์˜ต์…˜

addEventListener ์˜ 3๋ฒˆ์งธ ์ธ์ž์—” capture์™ธ์— 2๊ฐ€์ง€ ์˜ต์…˜์ด ๋” ์žˆ๋‹ค.

 

โถ once : ๊ฐ’ Boolean. `true`๋ฉด ์ด๋ฒคํŠธ๋Š” 1๋ฒˆ๋งŒ ์‹คํ–‰๋˜๊ณ  ๋ฆฌ์Šค๋„ˆ๊ฐ€ ์‚ญ์ œ๋œ๋‹ค

addEventListener('click', handler, { once: true }); // ํ˜น์€ { once: false }

 

โท passive : ๊ฐ’ Boolean. `true` ๋ฉด ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์— `preventDefault()` ๊ฐ€ ์žˆ์–ด๋„ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š”๋‹ค

 

`preventDefault` API ํ˜ธ์ถœ ์—ฌ๋ถ€๋ฅผ ๋ช…์‹œํ•˜๋Š” ์˜ต์…˜์ด๋‹ค. ๋ธŒ๋ผ์šฐ์ €๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ `preventDefault` ํ˜ธ์ถœ ์—ฌ๋ถ€๋ฅผ ๊ฐ์‹œํ•˜๋Š”๋ฐ, `passive` ์†์„ฑ์„ `true` ๋กœ ์คŒ์œผ๋กœ์จ ์ด๋Ÿฐ ๊ฐ์‹œ ๋น„์šฉ์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค. 

addEventListener('click', handler, { passive: true }); // ํ˜น์€ { passive: false }

 

๐Ÿ’ก ๋ช…์‹œํ•˜์ง€ ์•Š์•˜์„ ๋•Œ ๊ธฐ๋ณธ๊ฐ’์€ `false` ์ง€๋งŒ wheel, mousewheel, touchstart, touchmove ์ด๋ฒคํŠธ์—์„  ๊ธฐ๋ณธ๊ฐ’์ด `true` ์ธ ์  ์ฃผ์˜(Safari, IE ์ œ์™ธ) — ์ฐธ๊ณ 

 

๋ฆฌ์Šค๋„ˆ ์ œ๊ฑฐ removeEventListener

์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์ œ๊ฑฐํ•  ๋•Œ removeEventListener ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ฃผ์˜ํ•  ์ ์€ ์ด๋ฒคํŠธ๋ฅผ ๋“ฑ๋กํ–ˆ์„ ๋•Œ์˜ ํ•ธ๋“ค๋Ÿฌ(์ฝœ๋ฐฑ)์™€, capture ๋ฆฌ์Šค๋„ˆ ์˜ต์…˜(๋ฆฌ์Šค๋„ˆ 3๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜) ๊ฐ’์ด ์ผ์น˜ํ•ด์•ผ๋งŒ ์ œ๊ฑฐ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์ œ๊ฑฐํ•  ๋• ์ด๋ฒคํŠธ๋ฅผ ๋“ฑ๋กํ–ˆ์„ ๋•Œ์™€ ๋™์ผํ•œ ํ•ธ๋“ค๋Ÿฌ์™€ capture ์˜ต์…˜์„ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค.

 

๐Ÿ’ก `once` ๋‚˜ `passive` ์˜ต์…˜์€ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์ œ๊ฑฐํ•  ๋•Œ ๊ฒ€์‚ฌํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ผ์น˜ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

 

// ์ด๋ฒคํŠธ ๋“ฑ๋ก(3๋ฒˆ์งธ ์ธ์ž์— ์•„๋ฌด๊ฒƒ๋„ ๋ช…์‹œํ•˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ { capture: false }์™€ ๊ฐ™๋‹ค)
element.addEventListener('click', handler);

// ์ด๋ฒคํŠธ ์ œ๊ฑฐ
element.removeEventListener('click', handler); // ์ œ๊ฑฐ ์„ฑ๊ณต
element.removeEventListener('click', handler, false); // ์ œ๊ฑฐ ์„ฑ๊ณต
element.removeEventListener('click', handler, { capture: false }); // ์ œ๊ฑฐ ์„ฑ๊ณต
element.removeEventListener('click', handler, { passive: true }); // ์ œ๊ฑฐ ์„ฑ๊ณต
element.removeEventListener('click', handler, true); // ์ œ๊ฑฐ ์‹คํŒจ(capture ์˜ต์…˜์ด ๋‹ค๋ฅด๋ฏ€๋กœ)
element.removeEventListener('click', handler2, false); // ์ œ๊ฑฐ ์‹คํŒจ(ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋‹ค๋ฅด๋ฏ€๋กœ)

 

์ด๋ฒคํŠธ ๋‹จ๊ณ„ | Event Phase

<div>
  DIV
  <p>
    P<span>SPAN</span>
  </p>
</div>;
for (let elem of document.querySelectorAll('*')) {
  // ์ฒซ๋ฒˆ์งธ ๋ฆฌ์Šค๋„ˆ
  elem.addEventListener('click', (e) => alert(`์บก์ณ๋ง: ${elem.tagName}`), true);
  // ๋‘๋ฒˆ์งธ ๋ฆฌ์Šค๋„ˆ
  elem.addEventListener('click', (e) => alert(`๋ฒ„๋ธ”๋ง: ${elem.tagName}`));
}

 

์œ„ ์ฝ”๋“œ์˜ ์ด๋ฒคํŠธ ํ๋ฆ„์€ ์•„๋ž˜ 3๊ฐ€์ง€ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์นœ๋‹ค.

 

  1. Capturing ๋‹จ๊ณ„ : ์ด๋ฒคํŠธ๊ฐ€ ํ•˜์œ„ ์š”์†Œ๋กœ ์ „ํŒŒ๋˜๋Š” ๋‹จ๊ณ„
  2. Target ๋‹จ๊ณ„ : ์ด๋ฒคํŠธ๊ฐ€ (์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ)Target ์š”์†Œ์— ์ „๋‹ฌ๋˜๋Š” ๋‹จ๊ณ„
  3. Bubbling ๋‹จ๊ณ„ : ์ด๋ฒคํŠธ๊ฐ€ ์ƒ์œ„ ์š”์†Œ๋กœ ์ „ํŒŒ๋˜๋Š” ๋‹จ๊ณ„

 

HTML ํ•˜์œ„์— ์žˆ๋Š” ๋ชจ๋“  ํƒœ๊ทธ์— ์ด๋ฒคํŠธ ์บก์ฒ˜๋ง / ๋ฒ„๋ธ”๋ง ์ˆœ์„œ๋กœ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ• ๋‹นํ•˜๊ณ  ๊ฐ€์žฅ ์•„๋ž˜์— ์žˆ๋Š” span ํƒœ๊ทธ๋ฅผ ํด๋ฆญํ•ด๋ณด๋ฉด ์•„๋ž˜ ์ˆœ์„œ๋Œ€๋กœ ์ด๋ฒคํŠธ๊ฐ€ ์ „๋‹ฌ๋˜๋Š”๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

  1. HTMLBODYDIVP (์ด๋ฒคํŠธ ์บก์ฒ˜๋ง ๋‹จ๊ณ„ / 1๋ฒˆ์งธ ๋ฆฌ์Šค๋„ˆ)
  2. SPAN (Target ๋‹จ๊ณ„ / ์บก์ฒ˜๋ง, ๋ฒ„๋ธ”๋ง ๋ฆฌ์Šค๋„ˆ ๋‘˜ ๋‹ค ์„ค์ •ํ–ˆ์œผ๋ฏ€๋กœ 2๋ฒˆ ํ˜ธ์ถœ)
  3. PDIVBODYHTML (์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง ๋‹จ๊ณ„ / 2๋ฒˆ์งธ ๋ฆฌ์Šค๋„ˆ)

 

๐Ÿ’ก `event.eventPhase` ๋ฉ”์„œ๋“œ๋กœ ์ด๋ฒคํŠธ ์‹คํ–‰ ๋‹จ๊ณ„๋ฅผ ํ™•์ธํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์€ `0` ์ด๋ฒคํŠธ ์—†์Œ, `1` ์ด๋ฒคํŠธ ์บก์ฒ˜, `2` ์ด๋ฒคํŠธ ํƒ€๊ฒŸ, `3` ์ด๋ฒคํŠธ ๋ฒ„๋ธ”

 

See the Pen Event Phase ์ด๋ฒคํŠธ ํ๋ฆ„ by ColorFilter (@colorfilter) on CodePen.

 

 

e.target / e.currentTarget


  • event.currentTarget : ํ˜„์žฌ ์‹คํ–‰์ค‘์ธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ํ• ๋‹น๋˜์–ด ์žˆ๋Š” ์š”์†Œ(์ด๋ฒคํŠธ๋ฅผ ํ•ธ๋“ค๋งํ•˜๊ณ  ์žˆ๋Š” ํ˜„์žฌ ์š”์†Œ)
  • event.target : ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ์š”์†Œ. ์ด๋ฒคํŠธ ์ „ํŒŒ๊ฐ€ ์ง„ํ–‰๋˜๋”๋ผ๋„ ๋ณ€ํ•˜์ง€ ์•Š๋Š”๋‹ค

 

์•„๋ž˜ ์ฝ”๋“œ์—์„œ <p> ํƒœ๊ทธ์˜ ๋ถ€๋ชจ ์š”์†Œ์ธ <div>์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ• ๋‹นํ–ˆ๋‹ค. p ํƒœ๊ทธ๋ฅผ ํด๋ฆญํ•˜๋ฉด, ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ณณ(p ํƒœ๊ทธ)์ด๋ฏ€๋กœ target์ด ๋˜๊ณ , ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•ด๋†“์€ div๋Š” currentTarget์ด ๋œ๋‹ค.

 

<p> ํƒœ๊ทธ๋Š” ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง์œผ๋กœ ์ด๋ฒคํŠธ๋ฅผ ์œ„์ž„๋ฐ›์•˜๊ธฐ ๋•Œ๋ฌธ์—, <div> ํƒœ๊ทธ์˜ addEventListener๋กœ <p> ํƒœ๊ทธ ์ •๋ณด๊ฐ€ ์ „๋‹ฌ๋œ ๊ฒƒ์ด๋‹ค.

<div>
  DIV ํƒœ๊ทธ
  <p>P ํƒœ๊ทธ</p>
</div>;
const $div = document.querySelector('div');
$div.addEventListener('click', (e) => {
  console.log(`currentTarget: ${e.currentTarget.tagName}`);
  console.log(`target: ${e.target.tagName}`);
});

// <p> ํƒœ๊ทธ ํด๋ฆญ์‹œ...
// "currentTarget: DIV"
// "target: P"

 

See the Pen event.currentTarget vs event.target by ColorFilter (@colorfilter) on CodePen.

 

 

์ด๋ฒคํŠธ ์ „ํŒŒ ์ค‘๋‹จ Stop Propagation


์•„๋ž˜ ์ „ํŒŒ์ค‘๋‹จ API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, โžŠ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง์ผ ๋• ํด๋ฆญํ•œ ์š”์†Œ์˜ ์ด๋ฒคํŠธ๋งŒ ๋ฐœ์ƒ์‹œํ‚ค๊ณ  ์ƒ์œ„ ์š”์†Œ๋กœ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š๋Š”๋‹ค. โž‹์ด๋ฒคํŠธ ์บก์ฒ˜๋ง์ผ ๋• ํด๋ฆญํ•œ ์š”์†Œ์˜ ์ตœ์ƒ์œ„ ์š”์†Œ์˜ ์ด๋ฒคํŠธ๋งŒ ๋™์ž‘์‹œํ‚ค๊ณ  ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ์š”์†Œ๋ฅผ ์ œ์™ธํ•œ ๋‹ค๋ฅธ ํ•˜์œ„ ์š”์†Œ์—” ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š๋Š”๋‹ค.

const eventHandler = (event) => {
    // ์ƒ๋žต...
    event.stopPropagation();
    event.preventDefault();
    event.stopImmediatePropagation();
}

 

  • event.preventDefault() : ์ด๋ฒคํŠธ ๊ธฐ๋ณธ ๋™์ž‘ ์ค‘๋‹จ
  • event.stopPropagation() : ์ด๋ฒคํŠธ ์ „ํŒŒ ์ค‘๋‹จ
  • event.stopImmediatePropagation() : ์ด๋ฒคํŠธ ์ „ํŒŒ ์ค‘๋‹จ. ํ˜„์žฌ ๋ ˆ๋ฒจ์— ๊ฑธ๋ ค ์žˆ๋Š” ๋‹ค๋ฅธ ์ด๋ฒคํŠธ๋„ ์ค‘๋‹จ.

 

์ด๋ฒคํŠธ ์ „ํŒŒ ์ค‘๋‹จ API๋ฅผ ์‚ฌ์šฉํ•œ ์˜์—ญ์€ Dead Area๊ฐ€ ๋˜๋ฏ€๋กœ click ๊ฐ™์€ ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ๋ฅผ ๋ถ„์„ํ•  ๋•Œ Dead Area๋Š” ๋ถ„์„ ํ•  ์ˆ˜ ์—†๊ฒŒ ๋œ๋‹ค. ์•„ํ‚คํ…์ฒ˜๋ฅผ ์ž˜ ๊ณ ๋ คํ•œ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์ด๋ฒคํŠธ ์ „ํŒŒ ์ค‘๋‹จ API๋ฅผ ๋‚จ์šฉํ•˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.

์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง์„ ๋ง‰์•„์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๊ฑฐ์˜ ์—†์Šต๋‹ˆ๋‹ค. ๋ฒ„๋ธ”๋ง์„ ๋ง‰์•„์•ผ ํ•ด๊ฒฐ๋˜๋Š” ๋ฌธ์ œ๋ผ๋ฉด ์ปค์Šคํ…€ ์ด๋ฒคํŠธ ๋“ฑ์„ ์‚ฌ์šฉํ•ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค... ํ•ธ๋“ค๋Ÿฌ์˜ event ๊ฐ์ฒด์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ด ๋‹ค๋ฅธ ํ•ธ๋“ค๋Ÿฌ์—์„œ ์ฝ์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋ฉด, ์•„๋ž˜์ชฝ์—์„œ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๋Š”์ง€๋ฅผ ๋ถ€๋ชจ ์š”์†Œ์˜ ํ•ธ๋“ค๋Ÿฌ์—๊ฒŒ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์ด ๋ฐฉ๋ฒ•์œผ๋กœ๋„ ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง์„ ํ†ต์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. — JavaScript Info

 

stopPropagation() vs stopImmediatePropagation()

๐Ÿ’ก 1๊ฐœ ์š”์†Œ์— ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ ํ• ๋‹นํ–ˆ๋‹ค๋ฉด ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ• ๋‹นํ•œ ์ˆœ์„œ(์œ„ → ์•„๋ž˜)๋Œ€๋กœ ์ž‘๋™ํ•œ๋‹ค.

 

์•„๋ž˜์ฒ˜๋Ÿผ 1๊ฐœ ์š”์†Œ์— 2๊ฐœ์˜ ํด๋ฆญ ์ด๋ฒคํŠธ๊ฐ€ ๊ฑธ๋ ค ์žˆ๊ณ , ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์— stopPropagation()์„ ๋ช…์‹œํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณธ๋‹ค. span ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ํด๋ฆญํ•˜๋ฉด ์ด๋ฒคํŠธ ์ „ํŒŒ๋Š” ์ค‘๋‹จ๋˜์ง€๋งŒ ํด๋ฆญํ•œ ์—˜๋ฆฌ๋จผํŠธ์— ๊ฑธ๋ ค ์žˆ๋Š” ํ•ธ๋“ค๋Ÿฌ ๋ชจ๋‘ ์‹คํ–‰๋œ๋‹ค(ํ•ด๋‹น ์—˜๋ฆฌ๋จผํŠธ์— ๊ฑธ๋ ค ์žˆ๋Š” ๋ชจ๋“  ์ด๋ฒคํŠธ ํ˜ธ์ถœ).

const $span = document.querySelector('#span');
$span.addEventListener('click', (e) => eventHandler); // 1๋ฒˆ์งธ ์ด๋ฒคํŠธ
$span.addEventListener('click', (e) => eventHandler); // 2๋ฒˆ์งธ ์ด๋ฒคํŠธ

 

stopImmediatePropagation()์€ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ์—˜๋ฆฌ๋จผํŠธ์— ๊ฑธ๋ ค ์žˆ๋Š” ๋‹ค๋ฅธ ์ด๋ฒคํŠธ์˜ ์ „ํŒŒ๋„ ์ค‘๋‹จ์‹œํ‚จ๋‹ค. ์œ„ ์ฝ”๋“œ๋ฅผ ์˜ˆ๋กœ๋“ค๋ฉด span ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ํด๋ฆญํ•œ ์ˆœ๊ฐ„ ์ด๋ฒคํŠธ ์ „ํŒŒ๊ฐ€ ์ค‘๋‹จ๋˜๋ฉด์„œ 1๋ฒˆ์งธ ์ด๋ฒคํŠธ(ํ•ธ๋“ค๋Ÿฌ)๋งŒ ํ˜ธ์ถœ๋œ๋‹ค. 2๋ฒˆ์งธ ์ด๋ฒคํŠธ(ํ•ธ๋“ค๋Ÿฌ)๋Š” ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค.

 

See the Pen [Event] stopPropagation() vs stopImmediatePropagation() by ColorFilter (@colorfilter) on CodePen.

 

 

preventDefault()

๐Ÿ’ก ํฌ์ปค์Šค๊ฐ€ ํ•ด์ œ๋˜๋Š” `blur` ์ด๋ฒคํŠธ๋ฅผ ๋ฐฉ์ง€ํ•  ๋•Œ๋„ `preventDefault` ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค — ์ฐธ๊ณ  ๋…ธํŠธ

 

<a id="a" href="https://romantech.net" target="_blank">
  A ์˜์—ญ ๋งํฌ
</a>;

 

<a> ํƒœ๊ทธ๋Š” href ์†์„ฑ์— ๋ช…์‹œํ•œ URL๋กœ ์ด๋™ํ•˜๋Š” ์ด๋ฒคํŠธ ๋™์ž‘์„ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. <a> ํƒœ๊ทธ ์ฒ˜๋Ÿผ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” (์ด๋ฒคํŠธ)๋™์ž‘์„ ๋ฐฉ์ง€ํ•˜๊ณ  ์‹ถ์„ ๋• ํ•ธ๋“ค๋Ÿฌ์— preventDefault()๋ฅผ ๋ช…์‹œํ•˜๋ฉด ๋œ๋‹ค. ๊ทธ๋Ÿผ <a> ํƒœ๊ทธ๋Š” ํด๋ฆญํ•ด๋„ ๋งํฌ๋กœ ์ด๋™ํ•˜์ง€ ์•Š๊ณ , <form> ํƒœ๊ทธ๋Š” submit ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ๋„ ์„œ๋ฒ„๋กœ ์ž๋™ ์ „์†ก๋˜์ง€ ์•Š๋Š”๋‹ค.

 

See the Pen [Event] preventDefault() by ColorFilter (@colorfilter) on CodePen.

 

 

์ด๋ฒคํŠธ ์œ„์ž„ | Event Delegation


See the Pen Event Delegation ์ด๋ฒคํŠธ ์œ„์ž„ by ColorFilter (@colorfilter) on CodePen.

 

์ด๋ฒคํŠธ ์œ„์ž„์€ ํ•˜์œ„ ์š”์†Œ์— ์ด๋ฒคํŠธ๋ฅผ ๋ถ™์ด์ง€ ์•Š๊ณ , ์ƒ์œ„ ์š”์†Œ์—์„œ ํ•˜์œ„ ์š”์†Œ์˜ ์ด๋ฒคํŠธ๋ฅผ ์ œ์–ดํ•˜๋Š” ๋ฐฉ์‹(ํŒจํ„ด)์ด๋‹ค. ์•„๋ž˜ ์˜ˆ์ œ์—์„œ ํ•  ์ผ ๋ชฉ๋ก์— ์žˆ๋Š” ์ฒดํฌ๋ฐ•์Šค์— ์ฒดํฌํ•˜๋ฉด, ์ฒดํฌํ•œ ํ•  ์ผ ํ…์ŠคํŠธ๊ฐ€ ์šฐ์ธก DoneList์— ์ถ”๊ฐ€๋œ๋‹ค. ์ฒดํฌ๋ฐ•์Šค <input type="checkbox">์— ์ผ์ผ์ด ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋ถ™์ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ์ƒˆ๋กœ์šด ํ•  ์ผ์„ ์ถ”๊ฐ€ํ•  ๋•Œ๋งˆ๋‹ค ์ด๋ฒคํŠธ๋ฅผ ๋ถ™์—ฌ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฒˆ๊ฑฐ๋กญ๋‹ค.

 

์ด๋Ÿฐ ๋ฒˆ๊ฑฐ๋กœ์›€์„ ํ•ด์†Œํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ ์ด๋ฒคํŠธ ์œ„์ž„ ํŒจํ„ด์ด๋‹ค. ๊ฐ€์žฅ ์ƒ์œ„์— ์žˆ๋Š” <ul> ํƒœ๊ทธ์—๋งŒ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์ถ”๊ฐ€ํ•ด๋‘๋ฉด, ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง์œผ๋กœ ์ธํ•ด ํ•˜์œ„ ์š”์†Œ์—์„œ ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•œ๋‹ค. ์ƒˆ๋กœ์šด ํ•  ์ผ(์ฒดํฌ๋ฐ•์Šค)์ด ์ถ”๊ฐ€๋ผ๋„ ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜๋™์œผ๋กœ ๋ถ™์ด์ง€ ์•Š์•„๋„ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํŽธ๋ฆฌํ•˜๋‹ค.

 

๐Ÿ’ก radio ํƒ€์ž…์˜ `<input>` ์€ 1๊ฐœ๋งŒ ์„ ํƒ ํ•  ์ˆ˜ ์žˆ๊ณ , checkbox ํƒ€์ž…์˜ `<input>` ์€ ์—ฌ๋Ÿฌ ๊ฐœ ์„ ํƒ ํ•  ์ˆ˜ ์žˆ๋‹ค. `name` ์†์„ฑ์€ ์ฒดํฌ๋ฐ•์Šค์˜ ์ด๋ฆ„์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ ๊ฐ™์€ ๋ถ„๋ฅ˜์˜ ์ฒดํฌ๋ฐ•์Šค๋ฅผ ๊ทธ๋ฃน์œผ๋กœ ๋ฌถ์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. React, Vue์—์„œ ํŠน์ • `<input>` ํƒœ๊ทธ๋ฅผ ์‹๋ณ„ํ•  ๋•Œ `name` ์†์„ฑ์„ ํ™œ์šฉํ•˜๊ธฐ๋„ ํ•œ๋‹ค. form ํƒœ๊ทธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋ฉด `<input>` ์˜ `name`, `value` ์†์„ฑ ๊ฐ’์ด `...?name=value` ํ˜•ํƒœ๋กœ ์ „์†ก๋œ๋‹ค. — ์ฐธ๊ณ  ๋งํฌ 

 

๐Ÿ’ก `<label>` ํƒœ๊ทธ์™€ `<input>` ํƒœ๊ทธ๋ฅผ ์—ฐ๊ฒฐํ•˜๋ฉด `<label>` ์˜ textContent ์˜์—ญ๋งŒ ํด๋ฆญํ•ด๋„ input ์ฒดํฌ๋ฐ•์Šค๋ฅผ ํ•ธ๋“ค๋งํ•  ์ˆ˜ ์žˆ๋‹ค. `<label>` ํƒœ๊ทธ์˜ `for` ์†์„ฑ๊ณผ `<input>` ํƒœ๊ทธ์˜ `id` ์†์„ฑ ๊ฐ’์„ ๋™์ผํ•˜๊ฒŒ ์ž…๋ ฅํ•˜๋ฉด ๋‘ ํƒœ๊ทธ๋ฅผ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค. ์ ‘๊ทผ์„ฑ์„ ๊ณ ๋ คํ•ด `<input>` ๊ณผ `<label>` ํƒœ๊ทธ๋Š” ๊ฐ™์ด ์“ฐ๋Š”๊ฒŒ ์ข‹๋‹ค. `<input>` ํƒœ๊ทธ๊ฐ€ `<label>` ์•ˆ์ชฝ์— ์žˆ๋‹ค๋ฉด ์—ฐ๊ฒฐ๋œ ์ƒํƒœ๊ฐ€ ๋˜๋ฏ€๋กœ `for`, `id` ๋ฅผ ์ž…๋ ฅํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค. — ์ฐธ๊ณ  ๋งํฌ

 

<ul class="itemList">
  <li>
    <input type="checkbox" id="item1" />
    <label for="item1">Learn JavaScript</label>
  </li>
</ul>;
const $itemList = document.querySelector('.itemList');
$itemList.addEventListener('input', updateDoneList);
// updateDoneList ํ•ธ๋“ค๋Ÿฌ๋Š” ์ฒดํฌํ•œ ํ•  ์ผ์„ DoneList์— ์ถ”๊ฐ€ํ•œ๋‹ค.
// input ์ด๋ฒคํŠธ ํƒ€์ž…์€ <input>, <select>, <textarea> ์š”์†Œ์˜ value ์†์„ฑ์ด ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ

 

elem.closest()

addEventListener์˜ ์ด๋ฒคํŠธ ํƒ€์ž…์„ 'input'์œผ๋กœ ์ž…๋ ฅํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— <input> ํƒœ๊ทธ์— ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ๋งŒ ํ˜ธ์ถœ๋œ๋‹ค. 'input' ์ด๋ฒคํŠธ ํƒ€์ž…์€ <input> <select> <textarea> ์š”์†Œ์˜ value ์†์„ฑ์ด ๋ฐ”๋€” ๋•Œ๋งŒ ํ˜ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

๐Ÿ’ก elem.closest(selector) ๋ฉ”์„œ๋“œ๋กœ ๋ถ€๋ชจ ์š”์†Œ๋ฅผ ์‰ฝ๊ฒŒ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค. closest() ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋ช…์‹œํ•œ ๋ฌธ์ž์—ด๊ณผ ์ผ์น˜ํ•˜๋Š” ๋…ธ๋“œ๋ฅผ ์ฐพ์„ ๋•Œ๊นŒ์ง€ ์ž์‹ (e.target)๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ๋ถ€๋ชจ ์š”์†Œ ๋‹จ์œ„๋กœ ํƒ์ƒ‰ํ•œ๋‹ค(๋ฌธ์„œ ๋ฃจํŠธ๊นŒ์ง€). ์กฐ๊ฑด์„ ๋งŒ์กฑํ•œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ(๋ถ€๋ชจ ์š”์†Œ๋ฅผ ์ฐพ์„ ๋• ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋ถ€๋ชจ), ์—†์œผ๋ฉด null ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ž์‹ ๋ถ€ํ„ฐ ํƒ์ƒ‰ํ•˜๋ฏ€๋กœ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ์—˜๋ฆฌ๋จผํŠธ ์ž์‹ ์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

๋งŒ์•ฝ ์ด๋ฒคํŠธ ํƒ€์ž…์„ click ์œผ๋กœ ์ž…๋ ฅํ–ˆ๋‹ค๋ฉด <input> ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, <label> <li> ํƒœ๊ทธ์˜ ์ด๋ฒคํŠธ๋„ ๊ฐ์ง€ํ•œ๋‹ค. ์ด ์ƒํ™ฉ์—์„œ <input> ํƒ€์ž… ์ด๋ฒคํŠธ๋งŒ ์‚ฌ์šฉํ•˜๋ ค๋ฉด elem.closest() ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

// addToDoneList ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ
const updateDoneList = (e) => {
  // ๋„˜์–ด์˜จ ์ด๋ฒคํŠธ๊ฐ€ checkbox ํƒ€์ž…์˜ input ์š”์†Œ๋ผ๋ฉด, ํ•ด๋‹น ์š”์†Œ ์ •๋ณด๊ฐ€ input ๋ณ€์ˆ˜์— ๋‹ด๊ธด๋‹ค
  // ์…€๋ ‰ํ„ฐ์— ๋ช…์‹œํ•œ ๋…ธ๋“œ๋ฅผ ์ฐพ์ง€ ๋ชปํ–ˆ๋‹ค๋ฉด null ๋ฐ˜ํ™˜
  const input = e.target.closest('input[type=checkbox]');
  if (input) {
    // ...
  }
};

 

๋ฐ์ดํ„ฐ ์†์„ฑ | Data Attribute

์–ด๋Š ์—˜๋ฆฌ๋จผํŠธ์—๋“  data- ๋กœ ์‹œ์ž‘ํ•˜๋Š” ์†์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ํ™”๋ฉด์—” ๋ณด์ด์ง€ ์•Š๋Š” ํ…์ŠคํŠธ๋‚˜ ์ •๋ณด๋ฅผ ์—˜๋ฆฌ๋จผํŠธ์— ๋‹ด์•„๋‘˜ ๋•Œ ์œ ์šฉํ•˜๋‹ค. React๋‚˜ Vue์—์„œ ๋ฆฌ์ŠคํŠธ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ๋ Œ๋”ํ•  ๋•Œ key๋ฅผ ์ง€์ •ํ•˜๋Š”๋ฐ, ์ด๊ฒƒ ์—ญ์‹œ ๋ฐ์ดํ„ฐ ์†์„ฑ์„ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

<li data-key="item3">Do exercise</li>;

 

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„  elem.dataset ๊ฐ์ฒด๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

e.target.dataset.key; // item3
document.querySelect('li').dataset.key; // item3

 

๋ฐ์ดํ„ฐ ์†์„ฑ์€ HTML ์†์„ฑ์ด๊ธฐ ๋•Œ๋ฌธ์— CSS๋ฅผ ํ†ตํ•ด ์ ‘๊ทผํ•ด์„œ ํ™”๋ฉด์— ๋ณด์ด๋„๋ก ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

li::before {
  content: attr(data-key);
}

 

๊ฐ ๋ฐ์ดํ„ฐ ๊ฐ’์— ๋”ฐ๋ผ ์Šคํƒ€์ผ์„ ๋‹ค๋ฅด๊ฒŒ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

li[data-key='item3'] {
  color: red;
}

 

๋ฐ์ดํ„ฐ ์†์„ฑ๊ณผ ์ด๋ฒคํŠธ ์œ„์ž„ ํ™œ์šฉ

์ €์žฅํ•˜๊ธฐ, ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋“ฑ์˜ ๋ฒ„ํŠผ์„ ๊ตฌํ˜„ํ•ด์•ผ ๋œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณธ๋‹ค. ๊ฐ ๋ฒ„ํŠผ ์•ก์…˜์˜ ๋ฉ”์„œ๋“œ๋Š” ์ด๋ฏธ ๊ตฌํ˜„๋œ ์ƒํƒœ๋‹ค. ๋‹ค์Œ ์Šคํ…์€ ๋ฒ„ํŠผ๊ณผ ๋ฉ”์„œ๋“œ๋ฅผ ์—ฐ๊ฒฐํ•  ์ฐจ๋ก€. ์ด๋•Œ ๊ฐ ๋ฒ„ํŠผ์— ์ผ์ผ์ด ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ• ๋‹นํ•˜์ง€ ์•Š๊ณ  ์ด๋ฒคํŠธ ์œ„์ž„๊ณผ ๋ฐ์ดํ„ฐ ์†์„ฑ์„ ์‚ฌ์šฉํ•ด์„œ ๋”์šฑ ์„ธ๋ จ๋˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

<div id="menu">
  <button data-action="save">์ €์žฅํ•˜๊ธฐ</button>
  <button data-action="load">๋ถˆ๋Ÿฌ์˜ค๊ธฐ</button>
  <button data-action="search">๊ฒ€์ƒ‰ํ•˜๊ธฐ</button>
</div>;
const buttonAction = {
  save() {
    alert('์ €์žฅํ•˜๊ธฐ');
  },
  load() {
    alert('๋ถˆ๋Ÿฌ์˜ค๊ธฐ');
  },
  search() {
    alert('๊ฒ€์ƒ‰ํ•˜๊ธฐ');
  },
};

// id ์†์„ฑ์€ querySelector๋ฅผ ์“ฐ์ง€ ์•Š์•„๋„ id ์ด๋ฆ„์œผ๋กœ ์—˜๋ฆฌ๋จผํŠธ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.
menu.addEventListener('click', (e) => {
  const actionName = e.target.dataset.action; // save ํ˜น์€ load ํ˜น์€ search
  if (actionName) {
    buttonAction[actionName]();
  }
});

 

See the Pen ๋ฐ์ดํ„ฐ ์†์„ฑ๊ณผ ์ด๋ฒคํŠธ ์œ„์ž„ ํ™œ์šฉ ์˜ˆ์‹œ 1 by ColorFilter (@colorfilter) on CodePen.

 

 

ํ–‰๋™ ํŒจํ„ด — ์นด์šดํ„ฐ ๊ตฌํ˜„

๐Ÿ’ก `document` ๋ ˆ๋ฒจ์— ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ• ๋‹นํ•  ๋• ํ•ญ์ƒ `addEventListener`๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. `document`์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์€ ํ”„๋กœ์ ํŠธ์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

 

์ด๋ฒคํŠธ ์œ„์ž„๊ณผ ๋ฐ์ดํ„ฐ ์†์„ฑ์„ ํ™œ์šฉํ•ด ์„ ์–ธ์  ๋ฐฉ์‹์œผ๋กœ ํŠน์ • "ํ–‰๋™"์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜ ์˜ˆ์‹œ๋Š” ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์ˆซ์ž๊ฐ€ ์ฆ๊ฐ€ํ•˜๋Š” "ํ–‰๋™"์„ ๋ฐ์ดํ„ฐ ์†์„ฑ์˜ data-counter๋ฅผ ์ด์šฉํ•ด ๋ถ€์—ฌํ•œ ์˜ˆ์‹œ

<input type="button" value="1" data-counter />
<input type="button" value="2" data-counter />
document.addEventListener('click', (e) => {
  // ๋ฐ์ดํ„ฐ ์†์„ฑ์˜ ๊ฐ’์€ ์—†๊ณ  key(data-counter)๋งŒ ์žˆ๋‹ค๋ฉด ์กฐํšŒํ–ˆ์„ ๋•Œ ๋นˆ ๋ฌธ์ž์—ด๋กœ ๋‚˜์˜จ๋‹ค
  // ๋”ฐ๋ผ์„œ ์•„๋ž˜์ฒ˜๋Ÿผ !== undefined ์กฐ๊ฑด์„ ๋ช…์‹œํ•œ๋‹ค
  if (e.target.dataset.counter !== undefined) {
    event.target.value++;
  }
});

 

See the Pen ๋ฐ์ดํ„ฐ ์†์„ฑ๊ณผ ์ด๋ฒคํŠธ ์œ„์ž„ ํ™œ์šฉ ์˜ˆ์‹œ 2 - ์นด์šดํ„ฐ ๊ตฌํ˜„(ํ–‰๋™ ํŒจํ„ด) by ColorFilter (@colorfilter) on CodePen.

 

 

ํ–‰๋™ ํŒจํ„ด — ํ† ๊ธ€๋Ÿฌ ๊ตฌํ˜„

data-toggle-id ๋ฐ์ดํ„ฐ ์†์„ฑ์ด ์žˆ๋Š” ์š”์†Œ(์•„๋ž˜ ์˜ˆ์ œ์—์„œ button)๋ฅผ ํด๋ฆญํ•˜๋ฉด, ํ•ด๋‹น ๋ฐ์ดํ„ฐ ์†์„ฑ ๊ฐ’์„ id๋กœ ๊ฐ€์ง€๋Š” ์š”์†Œ๋ฅผ ๋ณด์ด๊ฑฐ๋‚˜ ์‚ฌ๋ผ์ง€๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ๋„ ํƒœ๊ทธ์— data-toggle-id ์†์„ฑ๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด(ํ† ๊ธ€ ํ–‰๋™์„ ์„ ์–ธ ํ•ด์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด) ์š”์†Œ์— ํ† ๊ธ€ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํŽธ๋ฆฌํ•˜๋‹ค.

 

๐Ÿ’ก html ํƒœ๊ทธ์— hidden ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ํ•ด๋‹น ์š”์†Œ๋ฅผ ํ™”๋ฉด์—์„œ ๊ฐ์ถœ ์ˆ˜ ์žˆ๋‹ค. ํ™”๋ฉด์—” ๋ณด์ด์ง€ ์•Š์ง€๋งŒ ์˜์—ญ์€ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜๋Š” visibility: hidden ๊ณผ๋Š” ๋‹ฌ๋ฆฌ, ๊ฐ์ถ˜ ์˜์—ญ๋„ ์‚ฌ๋ผ์ง„๋‹ค. display: none; ์†์„ฑ๊ณผ ๋น„์Šทํ•˜๋‹ค(CSS). ์Šคํฌ๋ฆฐ ๋ฆฌ๋” ๊ฐ™์€ ๋‹ค๋ฅธ ํ‘œ์‹œ ๋ฐฉ์‹์—๋„ ์ˆจ๊ฒจ์ง€๋ฏ€๋กœ ์ฃผ์˜ํ•œ๋‹ค.

<button data-toggle-id="subscribe-mail">๊ตฌ๋… ํผ ๋ณด๊ธฐ</button>

<section id="subscribe-mail" hidden>
  <form>์ด๋ฉ”์ผ<input type="email" /></form>
</section>
document.addEventListener('click', (e) => {
  const id = e.target.dataset.toggleId;
  if (!id) return;
  const elem = document.getElementById(id);
  elem.hidden = !elem.hidden;
});

 

See the Pen ๋ฐ์ดํ„ฐ ์†์„ฑ๊ณผ ์ด๋ฒคํŠธ ์œ„์ž„ ํ™œ์šฉ ์˜ˆ์‹œ 3 - ํ† ๊ธ€๋Ÿฌ ๊ตฌํ˜„(ํ–‰๋™ ํŒจํ„ด) by ColorFilter (@colorfilter) on CodePen.

 

 

๋ ˆํผ๋Ÿฐ์Šค


์œ ์šฉํ•œ ์‚ฌ์ดํŠธ

 

์ฐธ๊ณ  ์‚ฌ์ดํŠธ

 


๊ธ€ ์ˆ˜์ •์‚ฌํ•ญ์€ ๋…ธ์…˜ ํŽ˜์ด์ง€์— ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”
๋ฐ˜์‘ํ˜•