Event Capture, Propagation, Bubbling and Once

view
<div class="one">
    <div class="two">
        <div class="three"></div>
    </div>
</div>

์ด๋ ‡๊ฒŒ ํ™”๋ฉด์ด ๊ตฌ์„ฑ๋œ ํŽ˜์ด์ง€๊ฐ€ ์žˆ๋‹ค. one์ด ๊ฐ€์žฅ ๋ฐ”๊นฅ ์•ˆ์ชฝ์œผ๋กœ ๋“ค์–ด ๊ฐˆ์ˆ˜๋ก two - three๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค.

Bubbling

const divs = document.querySelectorAll('div');

function logText(e) {
  console.log(this.classList.value);
}

divs.forEach(div => div.addEventListener('click', logText));  

//div.two๋ฅผ ํด๋ฆญํ•  ๊ฒฝ์šฐ console์ฐฝ์—”
//two
//one 

//div.three๋ฅผ ํด๋ฆญํ•  ๊ฒฝ์šฐ
//three
//two
//one

console.log๋ฅผ this๋กœ ๋ฐ”๊พธ๊ณ  div.three๋ฅผ ํด๋ฆญํ•œ๋‹ค๋ฉด?

const divs = document.querySelectorAll('div');

function logText(e) {
  console.log(this);
}

divs.forEach(div => div.addEventListener('click', logText));  

//console ์ฐฝ์—”
//<div class="three"></div>
//<div class="two"></div>
//<div class="one"></div>

๊ทธ๋Ÿผ console ์ฐฝ์— ์ฐจ๋ก€๋Œ€๋กœ ๋‚˜์˜จ๋‹ค.

์—ฌ๋Ÿฌ๊ฐœ๊ฐ€ ๋‚ดํฌ๋œ ์š”์†Œ๋ฅผ ํด๋ฆญํ•˜๋Š” ๊ฒฝ์šฐ ๊ทธ์˜ ๋ถ€๋ชจ์š”์†Œ DOM๊นŒ์ง€ ํด๋ฆญ ๋˜๋Š” ํ˜„์ƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

Capture

javascript๊ฐ€ ์–ด๋–ป๊ฒŒ ์ผํ•˜๋Š”์ง€ ๋ณด์ž.

  1. modern browsers๋Š” capture๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ๊ฒƒ์„ ํ•œ๋‹ค.

  2. element๋ฅผ ํด๋ฆญํ•˜๋ฉด ๊ทธ๊ฒƒ์€ ์œ„์—์„œ ์•„๋ž˜๋กœ ํ˜๋Ÿฌ๋‚ด๋ฆฐ๋‹ค.

    • ๋ธŒ๋ผ์šฐ์ €๋Š” "๋„ˆ body๋„ ํด๋ฆญํ•˜๊ณ , one๋„ ํด๋ฆญํ•˜๊ณ  two๋„ ํด๋ฆญํ•˜๊ณ  three๋„ ํด๋ฆญํ–ˆ๋„ค" ํ•˜๊ณ  ์ธ์‹ํ•œ๋‹ค.

    • ์‹ค์ œ๋กœ ์œ„์—์„œ ์•„๋ž˜๋กœ ๋‚ด๋ ค๊ฐ€๋‹ค๊ฐ€, ๋ชจ๋“  ์ด๋ฒคํŠธ๋ฅผ ๋‚ด๊ฐ€ ํด๋ฆญํ•œ ๊ณณ์— "captures" ๋ฅผ ํ•˜๊ณ  ๋ณด๊ด€ํ•œ๋‹ค.

    • ํ•˜์ง€๋งŒ ์ด๋ฒคํŠธ๋Š” ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.

    • ๊ทธ๋Ÿผ ์ด์ œ ํด๋ฆญํ•œ ๊ณณ์—์„œ "bubble Up"์ด ์ผ์–ด๋‚œ๋‹ค.

  3. ๊ทธ๋ง์€ ์ฆ‰ ์•„๋ž˜์—์„œ ์œ„๋กœ ์ด๋ฒคํŠธ ํŠธ๋ฆฌ๊ฑฐ๊ฐ€ ์ผ์–ด๋‚œ๋‹ค.

  4. ๋ธŒ๋ผ์šฐ์ €๋Š” "์ข‹์•„ ์šฐ๋ฆฌ๊ฐ€ ์•Œ์•„๋‚ธ ์ง€๊ธˆ๊นŒ์ง€ ๋„ˆ๊ฐ€ ํด๋ฆญํ•œ ๋ชจ๋“  ๊ฒƒ๋“ค์„ ์‹œ์ž‘ํ• ๊ป˜" ๋ผ๊ณ  ๋งํ•œ๋‹ค.

  5. three -> two -> one -> body ๊นŒ์ง€!

addEventListener์˜ 3๋ฒˆ์งธ option์„ ์‚ฌ์šฉํ•˜์ž

divs.forEach(div => div.addEventListener('click', logText, {
  //์œ„์—์„œ ์•„๋ž˜๋กœ ํ๋ฅด๋Š” ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฑฐ๋‹ค.
  capture: true
}));

false๋กœ ๋ฐ”๊ฟ”์ฃผ์ž.

divs.forEach(div => div.addEventListener('click', logText, {
  //์œ„์—์„œ ์•„๋ž˜๋กœ ํ๋ฅด๋Š” ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฑฐ๋‹ค.
  capture: false
}));

Stop Propagation

๋˜ ํ•œ๊ฐ€์ง€ stop propagation์ด๋ผ ๋ถˆ๋ฆฌ๋Š”๊ฑธ ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

๋งŒ์•ฝ ๊ฐ€์žฅ ์•ˆ์ชฝ์— ์žˆ๋Š”๊ฑธ ํด๋ฆญํ•œ๋‹ค๋ฉด, ์ด๋ฒคํŠธ๊ฐ€ trigger ๋œ๋‹ค. parent์™€ ๊ทธ๊ฒƒ์˜ parent ๋ชจ๋‘๊ฐ€.

ํ•จ์ˆ˜๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค.

function logText(e) {
  console.log(this.classList.value);
  e.stopPropagation(); //stop bubbling! 
}

bubbling ํ•ด์ฃผ๋Š”๊ฑธ ๋ฉˆ์ถ”์–ด ์ค€๋‹ค. ๋‚˜๋Š” ์‚ฌ์‹ค ํ•˜๋‚˜๋งŒ ํด๋ฆญํ–ˆ์–ด ๋ผ๋Š” ๋œป์ด ๋  ์ˆ˜ ์žˆ๋‹ค.'ใ…' ๊ทธ๋Ÿผ ๋‚ด๊ฐ€ ๋ณธ๋ž˜ ์›ํ•˜๋˜ ํ•˜๋‚˜๋ฅผ ํด๋ฆญํ•˜๊ฒŒ ๋œ๋‹ค!

capture: true and stopPropagation()

function logText(e) {
  console.log(this.classList.value);
  e.stopPropagation(); // stop bubbling!
  // console.log(this);
}

divs.forEach(div => div.addEventListener('click', logText, {
  capture: true
}));

//console์—
//one๋งŒ ๋œฌ๋‹ค.

์™œ๋ƒ๋ฉด capture๊ฐ€ ๋‚ด๋ ค๊ฐˆ ๋•Œ one์— ๋„์ฐฉํ–ˆ์„ ๋•Œ stopPropagation์ด ์ผ์–ด๋‚œ๋‹ค. ๋”์ด์ƒ ๋‚ด๋ ค๊ฐ€์ง€ ๋ชปํ•˜๋Š” ๊ฒƒ์ด๋‹ค.'ใ…'/

Once

์ด๋ฒคํŠธ๊ฐ€ ๋”ฑ ํ•œ๋ฒˆ๋งŒ ์ผ์–ด๋‚˜๋„๋ก ํ•ด์ค€๋‹ค.

function logText(e) {
    console.log(this.classList.value);
    // e.stopPropagation(); // stop bubbling!
    // console.log(this);
}

divs.forEach(div => div.addEventListener('click', logText, {
    capture: false,
    once: true
}));

once๋ฅผ ์“ฐ๋ฉด ์ด๋ฒคํŠธ๊ฐ€ ์‹คํ–‰๋˜๊ณ  ๊ทธ๊ฒƒ์€ unbind๊ฐ€ ๋œ๋‹ค. unbind๋Š” removeEventListener ๋กœ ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

  1. ์ด๋ฒคํŠธ๊ฐ€ ์‹คํ–‰๋˜๊ณ  once๋กœ ์ธํ•˜์—ฌ

  2. addEventListener๋Š” unbind๊ฐ€ ๋œ๋‹ค.

div์š”์†Œ ๊ฐ ํ•œ๋ฒˆ์”ฉ ์ด๋ฒคํŠธ๊ฐ€ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋‹ค.

Example 2

html

<button></button>

js

button.addEventListener('click', () => {
    console.log('Click!!!');
}, {
    once: true
});

์ด๋ฒคํŠธ๋Š” ์ •๋ง ๋”ฑ ํ•œ๋ฒˆ๋งŒ ์‹คํ–‰๋œ๋‹ค!

htmlํŒŒ์ผ๋ณด๊ธฐ

Last updated

Was this helpful?