๐ ํ๋์ ์ดํดํ๋ ์ด๋ฒคํธ ํ๋ฆ ์ ์ด (๋ฒ๋ธ๋ง & ์บก์ฒ๋ง)
HTML ์ด๋ฒคํธ์ ํ๋ฆ
HTML ๋ฌธ์์ ๊ฐ ์๋ฆฌ๋จผํธ๋ค์ ์๋์ ๊ฐ์ด ํ๊ทธ ์์ ํ๊ทธ๊ฐ ์์นํ๋ ์์ผ๋ก ๊ณ์ธต์ ์ผ๋ก ์ด๋ฃจ์ด์ง์ ๋ณผ ์ ์๋ค. ์ด๋ฌํ ๊ณ์ธต์ ๊ตฌ์กฐ ํน์ง ๋๋ฌธ์ ๋ง์ผ HTML ์์์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ ์ฐ์์ ์ด๋ฒคํธ ํ๋ฆ์ด ์ผ์ด๋๊ฒ ๋๋ค.
์๋ฅผ๋ค์ด ์๋ 3๊ฐ๊ฐ ์ค์ฒฉ๋ ๋ฐ์ค ์์ญ์์ ๊ฐ์ฅ ์์ ์๋ฆฌ๋จผํธ์ธ p ๋ฐ์ค๋ฅผ ํด๋ฆญํ๋ฉด onclick ์ด๋ฒคํธ ์คํฌ๋ฆฝํธ๊ฐ p ๋ฟ๋ง ์๋๋ผ ๊ทธ์ ๋ถ๋ชจ์ธ div์ form ์๋ฆฌ๋จผํธ๋ ๋ฐ์ํจ์ ๋ณผ ์ ์๋ค.
<form onclick="alert('form')">FORM
<div onclick="alert('div')">DIV
<p onclick="alert('p')">P</p>
</div>
</form>
See the Pen event bubbleing 1 by barzz12 (@inpaSkyrim) on CodePen.
์ด๋ฌํ ํ์์ ์ด๋ฒคํธ ์ ํ(Event Propagation)๋ผ ๋ถ๋ฅด๋ฉฐ, ์ ํ ๋ฐฉํฅ์ ๋ฐ๋ผ ๋ฒ๋ธ๋ง๊ณผ ์บก์ฒ๋ง์ผ๋ก ๊ตฌ๋ถํ๋ค.
- ๋ฒ๋ธ๋ง(Bubbling) : ์์ ์์์์ ๋ฐ์ํ ์ด๋ฒคํธ๊ฐ ๋ฐ๊นฅ ๋ถ๋ชจ ์์๋ก ์ ํ (๊ธฐ๋ณธ๊ฐ)
- ์บก์ณ๋ง(Capturing) : ์์ ์์์์ ๋ฐ์ํ ์ด๋ฒคํธ๊ฐ ๋ถ๋ชจ ์์๋ถํฐ ์์ํ์ฌ ์์ชฝ ์์ ์์๊น์ง ๋๋ฌ
์ด๋ค ์ ํ ๋ฐฉํฅ์ ์ฌ์ฉํ ๊ฒ์ด๋๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ค์ ์ ํตํด ์ ์ดํ ์ ์์ผ๋ฉฐ ๋์ ๋์์๋ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
์ด๋ฒคํธ ์ ํ ํ๋ฆ
ํ์ค DOM ์ด๋ฒคํธ์์ ์ ์ํ ์ด๋ฒคํธ ํ๋ฆ์ ๋ค์ 3๊ฐ์ง ๋จ๊ณ๊ฐ ์๋ค.
- ์บก์ฒ๋ง ๋จ๊ณ : ์ด๋ฒคํธ๊ฐ ํ์ ์์๋ก ์ ํ๋๋ ๋จ๊ณ
- ํ๊น ๋จ๊ณ : ์ด๋ฒคํธ๊ฐ ์ค์ ํ๊น ์์์ ์ ๋ฌ๋๋ ๋จ๊ณ
- ๋ฒ๋ธ๋ง ๋จ๊ณ : ์ด๋ฒคํธ๊ฐ ์์ ์์๋ก ์ ํ๋๋ ๋จ๊ณ
์๋ html๋ฌธ์์ ํ
์ด๋ธ ์์ <td>๋ฅผ ํด๋ฆญํ๋ฉด ์ด๋ป๊ฒ ์ด๋ฒคํธ๊ฐ ํ๋ฅด๋์ง ์๋ ๊ทธ๋ฆผ์ ๋ณด๊ณ ์ดํดํด ๋ณด์.
โ<td>๋ฅผ ํด๋ฆญํ๋ฉด ์ด๋ฒคํธ๊ฐ ์ต์์ ์กฐ์์์ ์์ํด ์๋๋ก ์ ํ๋๋ค (์บก์ฒ๋ง ๋จ๊ณ)- ์ด๋ฒคํธ๊ฐ ํ๊น ์์์ ๋์ฐฉํด ๋ฆฌ์ค๋๋ฅผ ์คํํ๋ค (ํ๊น ๋จ๊ณ)
- ๊ทธ๋ฆฌ๊ณ ๋ค์ ์์๋ก ์ด๋ฒคํธ๋ฅผ ์ ํํ๋ค (๋ฒ๋ธ๋ง ๋จ๊ณ)
์ด์ฒ๋ผ ๋ธ๋ผ์ฐ์ ๋ ์ฌ์ฉ์๋ก๋ถํฐ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ๊ฐ์ฅ ์๋จ์ ์์๋ถํฐ ํ์์ ์์๊น์ง ๋ด๋ ค์ค๊ณ ๋ค์ ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ๋ ์์ผ๋ก ์ด๋ฒคํธ๋ฅผ ์ ๋ฌํ์ฌ ๋ฐ์ํ๋๋ก ํ๋ค. ๋ง์ผ ํ๊น ์์๊น์ง ์ด๋ฒคํธ๋ฅผ ์ ํํ๋ ๊ณผ์ ์์ ๊ทธ์ ๋ถ๋ชจ, ์กฐ์์๋ ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ๋ฑ๋ก๋์ด ์๋ค๋ฉด ์คํ๋๊ฒ ๋๋ค.
์ด๋ฒคํธ ์ ํ๊ฐ ์๋ ์ด์
๊ทธ๋ผ ์ ์ด๋ ๊ฒ ๋ณต์กํ๊ฒ ์ด๋ฒคํธ๊ฐ ๊ตฌ์ฑ๋์ด์ ธ ์์๊น? ์ด์ ๋ํด์ ๋ํ์ ์ผ๋ก ๋ค์ ๋๊ฐ์ง ์ด์ ์ ๋ ๋ฝ์ ์ ์์ ๊ฒ์ด๋ค.
1. ๋ ผ๋ฆฌ์ ์ธ ์ด์
๊ฐ๋ง ์๊ฐํด๋ณด๋ฉด ์ด๋ฒคํธ ์ ํ๋ ์ด์ฉ๋ฉด ๋น์ฐํ ํ์์ผ์ง๋ ๋ชจ๋ฅธ๋ค. ์์ ์์๊ฐ ๋ถ๋ชจ ์์ ์์ญ ์์ ์์นํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์์ ์์๋ง์ ํด๋ฆญํ์๋ค ํ๋๋ผ๋ ๋ค๋ฅธ ์๊ฐ์ผ๋ก ๋ณด๋ฉด ๋ถ๋ชจ ์์๋ ํด๋ฆญํ ์ ์ด ๋๊ธฐ ๋๋ฌธ์ด๋ค.
๋ง์ผ ์์ ๊ทธ๋ฆผ์์ ํ๊ฒ์ธ button ์์ญ์ ํด๋ฆญํด๋ div์์ญ ์์ ์๊ธฐ ๋๋ฌธ์ ๋ ผ๋ฆฌ์ ์ผ๋ก div ์์ญ์ ์ด๋ฒคํธ๋ ๊ฐ์ด ๋ฐ์ํ๋ ๊ฒ์ด ์ณ์ ๊ฒ์ด๋ค.
2. ์ฑ๋ฅ์ ์ธ ์ด์
๋ํ ์ด๋ฌํ ํน์ง ๋๋ฌธ์ ์ด๋ฒคํธ ๋ฑ๋ก ์ฝ๋๋ฅผ ์ค์ผ ์ ์๋ค๋ ์ฅ์ ๋ ์๋ค.
์๋ฅผ๋ค์ด ์๋์ ๊ฐ์ด ์ฌ๋ฌ๊ฐ์ ๋ฆฌ์คํธ๊ฐ ์์๋, ๋ช๋ฒ์งธ ๋ฆฌ์คํธ๋ฅผ ํด๋ฆญํ๋ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํค๊ณ ์ถ๋ค๊ณ ํ์.
<ul id="post-list">
<li id="post-1">Item 1</li>
<li id="post-2">Item 2</li>
<li id="post-3">Item 3</li>
<li id="post-4">Item 4</li>
<li id="post-5">Item 5</li>
<li id="post-6">Item 6</li>
</ul>
๋ง์ผ ์ด๋ฒคํธ ์ ํ ๊ฐ๋
์ด ์๋ค๋ฉด, <li> ์์ ๋ง๋ค ์ผ์ผํ ์ด๋ฒคํธ๋ฅผ ๋ฑ๋กํด์ผ ํ๋ ๋
ธ๊ฐ๋ค๋ฅผ ํผ์ณ์ผ ํ ์ง๋ ๋ชจ๋ฅธ๋ค. ํ์ง๋ง ๋ฒ๋ธ๋ง์ ํน์ฑ์ ํตํด ์ฐ๋ฆฌ๋ ๊ทธ ๋ถ๋ชจ ์์์ธ <ul> ์์์๋ง ์ด๋ฒคํธ๋ฅผ ๋ฑ๋กํ๋ฉด, ์ด๋ค ๋ช๋ฒ์งธ์ li ์์๋ฅผ ํด๋ฆญํ๋ ๋ถ๋ชจ ์์๋ก ์ด๋ฒคํธ๊ฐ ์ ํ๋๊ธฐ ๋๋ฌธ์ ์ํ๋ ๊ตฌํ์ ๊ฐ๋จํ๊ฒ ํ ์ ์๋ ๊ฒ์ด๋ค. ์ด ๊ธฐ๋ฒ์ ์ด๋ฒคํธ ์์์ด๋ผ ๋ถ๋ฅธ๋ค.
๋ฒ๋ธ๋ง & ์บก์ฒ๋ง ์๋ฆฌ
์ด๋ฒคํธ ๋ฒ๋ธ๋ง
๋ฒ๋ธ๋ง์ ํ ์์์ ์ด๋ฒคํธ๊ฐ ๋ฐ์๋๋ฉด, ๊ทธ ์์์ ๋ถ๋ชจ ์์์ ์ด๋ฒคํธ๋ ๊ฐ์ด ๋ฐ์๋๋ ์ด๋ฒคํธ ์ ํ๋ฅผ ๋งํ๋ค. ์ด๋ฒคํธ๊ฐ ์ ์ผ ๊น์ ๊ณณ์ ์๋ ์์์์ ์์ํด ๋ถ๋ชจ ์์๋ฅผ ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ๋ฉฐ ๋ฐ์ํ๋ ๋ชจ์์ด ๋ง์น ๋ฌผ์ ๊ฑฐํ(bubble)๊ณผ ๋ฎ์๊ธฐ ๋๋ฌธ์ ๋ช ๋ช ์ง์ด์ก๋ค.
๋ฒ๋ธ๋ง ๋ฑ๋ก
๋ธ๋ผ์ฐ์ ์ ์ด๋ฒคํธ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฒ๋ธ๋ง ๋ฐฉ์์ผ๋ก ์ด๋ฒคํธ๊ฐ ์ ํ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ addEventListener() ํจ์๋ก ์์์ ์ด๋ฒคํธ๋ฅผ ๋ฑ๋กํ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฒ๋ธ๋ง ์ ํ ๋ฐฉ์์ผ๋ก ์ด๋ฒคํธ๊ฐ ํ๋ฅด๊ฒ ๋์ด, ๋ง์ผ ์์ ์์์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ๋ถ๋ชจ ์์๋ ๋ฒ๋ธ๋ง ํตํด ์ด๋ฒคํธ๊ฐ ์ ํ๋์ด ๋ฆฌ์ค๋๊ฐ ํธ์ถ๋๊ฒ ๋๋ค.
// ๋ฒ๋ธ๋ง ๋์ (false ์๋ต ํด๋๋จ)
element.addEventListener('click', (e) => { ... }, false);
๊ฑฐ์ ๋ชจ๋ ์ด๋ฒคํธ๋ ๋ฒ๋ธ๋ง์ด ๋๋ค๊ณ ๋ณด๋ฉด ๋๋ค. ๋ค๋ง focus ์ด๋ฒคํธ์ ๊ฐ์ด ๋ฒ๋ธ๋ง ๋์ง ์๋ ์ด๋ฒคํธ๋ ์กด์ฌํ๊ธฐ๋ ํ๋ค.
๋ฒ๋ธ๋ง ํ๋ฆ
์๋์ ๊ฐ์ด ์กฐ์(ancestor), ๋ถ๋ชจ(parent), ์์(child) ์์๋ค์ด ์ค์ฒฉ๋์ด ์๋ค๊ณ ํ์. ๊ทธ๋ฆฌ๊ณ ์ด๋ค ์์์ ๊ฐ๊ฐ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ๋ฑ๋กํ์๋ค.
<div id="ancestor">
<div id="parent">
<div id="child"></div>
</div>
</div>
ancestor.addEventListener("click", (e) => {
console.log('ancestor clicked');
})
parent.addEventListener("click", (e) => {
console.log('parent clicked');
})
child.addEventListener("click", (e) => {
console.log('child clicked');
})
See the Pen stopPropagatoin by barzz12 (@inpaSkyrim) on CodePen.
๋ฒ๋ธ๋ง์ ์์ชฝ์์ ๋ฐ๊นฅ์ชฝ์ผ๋ก ์ด๋ฒคํธ๊ฐ ์ ํ ๋๋ ํ๋ฆ์ด๋ผ๊ณ ํ์๋ค. ๊ฐ์ฅ ์์ชฝ์ ์์ ์์๋ฅผ ํด๋ฆญํ์. ๊ทธ๋ฌ๋ฉด ์๋ฐ์คํฌ๋ฆฝํธ์ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ํธ์ถ ์์๋ ์๋์ ๊ฐ์ด ๋๋ค.
- child clicked
- parent clicked
- ancestor clicked
์ด๋ฒคํธ ์บก์ฒ๋ง
์บก์ฒ๋ง์ ํ ์์์ ์ด๋ฒคํธ๊ฐ ๋ฐ์๋๋ฉด, ๊ทธ ์์์ ์์ ์์์ ์ด๋ฒคํธ๋ ๊ฐ์ด ๋ฐ์๋๋ ์ด๋ฒคํธ ์ ํ๋ฅผ ๋งํ๋ค. ํ๋ง๋๋ก ๋ฒ๋ธ๋ง ๋ฐ๋๋ผ๊ณ ๋ณผ ์ ์๋ค. ๋ค๋ง, ์ค๋ฌด์์ ์์ฃผ ์ฐ์ด์ง๋ ์์ง๋ง ๊ฐ๋ ์ ์ฉํ ๊ฒฝ์ฐ๊ฐ ์์ด ์์๋ณผ ํ์๊ฐ ์๋ค.
์บก์ฒ๋ง ๋ฑ๋ก
๋ธ๋ผ์ฐ์ ์ ์ด๋ฒคํธ ์ ํ ๋ฐฉ์์ ๋ฒ๋ธ๋ง์ด ๊ธฐ๋ณธ๊ฐ์ด๊ธฐ ๋๋ฌธ์ ์บก์ฒ๋ง์ผ๋ก ์ค์ ํ๊ธฐ ์ํด์ ๋ณ๋์ ์ต์
์ ํจ์์ ์ฃผ์ด์ผ ํ๋ค. ์๋ฐ์คํฌ๋ฆฝํธ addEventListener() ํจ์์ 3๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ก true ๊ฐ์ ์ฃผ๋ฉด ์ด ์ด๋ฒคํธ ํ๊ฒ์ ์บก์ฒ๋ง์ ํตํด ์ด๋ฒคํธ๋ฅผ ์ ํ๋ฐ์ ํธ์ถ๋๊ฒ ๋๋ค.
// ์บก์ฒ๋ง ๋์
element.addEventListener('click', (e) => { ... }, true);
element.addEventListener('click', (e) => { ... }, {capture: true});
์ด๋ ๊ฒ ์ต์ ์ค์ ์ ํตํด ๋ฒ๋ธ๋ง or ์บก์ฒ๋ง ์ด๋ฒคํธ ์ ํ ๋์์ผ๋ก ๋ฑ๋กํ๋ ์ด์ ๋, ๋ธ๋ผ์ฐ์ ๋ ์บก์ณ๋ง์ผ๋ก ํ์ํ๊ณ ๋ฒ๋ธ๋ง์ผ๋ก ๋์์ค๋๋ฐ ๊ฐ๋ค๊ฐ ๋์์ค๋ ๊ณผ์ ์์ ์ด๋ฒคํธ๊ฐ ๋๊ฐ์ด ๋๋ฒ ์คํํ๊ธฐ ๋๋ฌธ์ด๋ค.
์บก์ฒ๋ง์ IE8 ์ดํ์์ ์ง์๋์ง ์๋๋ค.
์บก์ฒ๋ง ํ๋ฆ
์๋์ ๊ฐ์ด ์กฐ์(ancestor), ๋ถ๋ชจ(parent), ์์(child) ์์๋ค์ด ์ค์ฒฉ๋์ด ์๋ค๊ณ ํ์. ๊ทธ๋ฆฌ๊ณ ์ด๋ค ์์์ ๊ฐ๊ฐ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ๋ฑ๋กํ์๋ค. ์ด๋ ์บก์ฒ๋ง ํ๋ฆ์ ์ค์ฅํ๊ธฐ ์ํด true ๊ฐ์ ๋ฆฌ์ค๋ ๋งค๊ฐ๋ณ์์ ํ ๋น ํ์๋ค.
<div id="ancestor">
<div id="parent">
<div id="child"></div>
</div>
</div>
// addEventListener ํจ์ 3๋ฒ์งธ ๋งค๊ฐ๋ณ์์ true ํน์ {capture: true} ์ธ์๋ฅผ ์ฃผ๋ฉด ๋๋ค
ancestor.addEventListener("click", (e) => {
console.log('ancestor clicked');
}, true)
parent.addEventListener("click", (e) => {
console.log('parent clicked');
}, true)
child.addEventListener("click", (e) => {
console.log('child clicked');
}, true)
See the Pen stopPropagatoin1 by barzz12 (@inpaSkyrim) on CodePen.
์บก์ฒ๋ง์ ๋ฐ๋๋ก ๋ฐ๊นฅ์ชฝ์์ ์์ชฝ์ผ๋ก ์ด๋ฒคํธ๊ฐ ์ ํ ๋๋ ํ๋ฆ์ด๋ผ๊ณ ํ์๋ค. ๊ฐ์ฅ ์์ชฝ์ ์์ ์์๋ฅผ ํด๋ฆญํ์. ๊ทธ๋ฌ๋ฉด ์๋ฐ์คํฌ๋ฆฝํธ์ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ํธ์ถ ์์๋ ์๋์ ๊ฐ์ด ๋๋ค.
- ancestor clicked
- parent clicked
- child clicked
๋ฒ๋ธ๋ง + ์บก์ฒ๋ง ๋์ ์ค์ ํ๊ธฐ
๋น์ฐํ ์์์ ์บก์ฒ๋ง ๊ณผ ๋ฒ๋ธ๋ง ์ ํ๋ฅผ ๋ชจ๋ ํธ๋ค๋งํ์ฌ ์ด๋ฒคํธ ์ฒ๋ฆฌํ๋๋ก ํ ์๋ ์๋ค. ๋ค์๊ณผ ๊ฐ์ด ์ด๋ฒคํธ ๋ฆฌ์ค๋ ํจ์๋ฅผ ๋๊ฐ ์ค์ ํด์ฃผ๋ฉด ๋๋ ์ผ์ด๋ค.
// ๋ฒ๋ธ๋ง ํธ์ถ
child.addEventListener("click", (e) => {
console.log('child clicked');
})
// ์บก์ฒ๋ง ํธ์ถ
child.addEventListener("click", (e) => {
console.log('child clicked');
}, true)
See the Pen event bubbleing 4 by barzz12 (@inpaSkyrim) on CodePen.
๋ฐ๋ผ์ ๊ฐ์ฅ ์์ชฝ์ ์์ ์์๋ฅผ ํด๋ฆญํ๋ฉด ์ด๋ฒคํธ ๋ฆฌ์ค๋ ํธ์ถ ์์๋ ๋ง์น ์ํํ๋ ํํ๊ฐ ๋๋ค.
- ancestor clicked
- parent clicked
- child clicked
- child clicked
- parent clicked
- ancestor clicked
์ด๋ฒคํธ ์ ํ ์ ์ดํ๊ธฐ
โ ๏ธ ๋ฒ๋ธ๋ง & ์บก์ฒ๋ง ๋ฌธ์ ์
์ด๋ฒคํธ ์ ํ ๊ฐ๋ ์ ์ข๋ค. ๊ทธ๋ฐ๋ฐ ๋ง์ผ ๋ถ๋ชจ์ ์์ ๋๋ค ์ด๋ฒคํธ๋ฅผ ๋ฑ๋กํ ์ํ์์, ์์ ์์๋ง ํด๋ฆญํ์๋๋ง ์ด๋ฒคํธ๋ฅผ ๋ฐ์ํ๊ณ ๋ถ๋ชจ ์์๋ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํค๊ณ ์ถ์ง ์์ ์ํฉ์ด ์์ ๊ฒ์ด๋ค.
ํ์ง๋ง ๋ธ๋ผ์ฐ์ ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์บก์ฒ๋ง - ๋ฒ๋ธ๋ง์ผ๋ก ๋์ ๋๊ธฐ ๋๋ฌธ์ ์ด๋ฒคํธ ๋์ ์์ฒด๋ฅผ ๋ฐ๊ฟ์ ์๋ค. ๊ทธ๋ฆฌ๊ณ html ๊ตฌ์กฐ๋ฅผ ๋ด๋ ์์ ์์๊ฐ ๋ถ๋ชจ ์์ ์์ญ ์์ ์์นํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์์ ์์๋ง์ ํด๋ฆญํ์๋ค ํ๋๋ผ๋ ๋ค๋ฅธ ์๊ฐ์ผ๋ก ๋ณด๋ฉด ๋ถ๋ชจ ์์๋ ํด๋ฆญํ ์ ์ด ๋์ด ๋ ผ๋ฆฌ์ ์ผ๋ก ๊ตฌ์กฐ์ ์ผ๋ก ์ด๊ฒ์ด ์ณ๋ค.
๋ฐ๋ผ์ ๋ธ๋ผ์ฐ์ ์ ์ด๋ฒคํธ ๊ตฌ์กฐ๋ฅผ ๋ฐ๊ฟ์๋ ์๊ณ , ์๋ฆฌ๋จผํธ์ ์ด๋ฒคํธ ์ ํ๋ฅผ ๋ฐฉ์ง ์ฒ๋ฆฌ ํ๋ ์์ผ๋ก ํด๊ฒฐํ์ฌ์ผ ํ๋ค.
์ด๋ฒคํธ ์ ํ ๋ฐฉ์ง ๋ฐฉ๋ฒ
๐ e.stopPropagation()
stopPropagation() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ๋ฒ๋ธ๋ง ๋๋ ์บก์ฒ๋ง ์ค์ ์ ๋ฐ๋ผ ์์, ํ์๋ก ๊ฐ๋ ์ด๋ฒคํธ ์ ํ๋ฅผ ๋ง์ ์ ์๋ค.
ancestor.addEventListener("click", (e) => {
e.stopPropagation() // ์ด๋ฒคํธ ์ ํ ๋ฐฉ์ง
print('ancestor')
})
parent.addEventListener("click", (e) => {
e.stopPropagation() // ์ด๋ฒคํธ ์ ํ ๋ฐฉ์ง
print('parent')
})
child.addEventListener("click", (e) => {
e.stopPropagation() // ์ด๋ฒคํธ ์ ํ ๋ฐฉ์ง
print('child')
})
See the Pen event bubbleing 5 by barzz12 (@inpaSkyrim) on CodePen.
๊ฐ๊ฐ ์์๋ฅผ ํด๋ฆญํด๋ณด๋ฉด ๊ฐ ์๋ฆฌ๋จผํธ์ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ง ๋์๋จ์ ๋ณผ ์ ์๋ค.
๐ e.stopImmediatePropagation()
stopImmediatePropagation() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด, ์ด๋ฒคํธ ์ ํ์ ๋๋ถ์ด ํ์ ์ด๋ฒคํธ ์คํ์ ์ค์งํ๋ค.
์๋ฅผ ๋ค์ด ์๋์ ๊ฐ์ด ๋์ผํ child ์์์ ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ 2๊ฐ ๋ฑ๋ก ๋์ด ์์๋, ์ด๋ ํ ์กฐ๊ฑด์์ ํด๋ฆญ ์ด๋ฒคํธ๋ฅผ ๋๋ฒ ์คํํ์ง ์๊ณ ํ๋ฒ๋ง ์คํํ ๋ก ํ๊ธธ ์ํ๋ค๋ฉด ์ ์ฉํ๋ค.
child.addEventListener("click", (e) => {
if(์กฐ๊ฑด)
e.stopImmediatePropagation()
print('child')
})
child.addEventListener("click", (e) => {
print('child 2')
})
์ด์ฒ๋ผ ๋์ผํ ์์์ ํน์ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๋ ํธ๋ค๋ฌ๊ฐ ์ฌ๋ฌ ๊ฐ ์ผ๋, e.stopPropagation()์ ๋ฒ๋ธ๋ง์ ๋ง์์ฃผ์ง๋ง, ๋ค๋ฅธ ํ์ ํธ๋ค๋ฌ๋ค์ด ๋์ํ๋ ๊ฑด ๋ง์ง ๋ชปํ๊ธฐ ๋๋ฌธ์, ์์์ ํ ๋น๋ ๋ค๋ฅธ ํธ๋ค๋ฌ์ ๋์๋ ๋ง์ผ๋ ค๋ฉด e.stopImmediatePropagation() ๋ฅผ ์ฌ์ฉํ์ฌ์ผ ํ๋ค.
๐ e.target ์ผ๋ก ์กฐ๊ฑด ๊ฑธ์ด ๋ฐฉ์ง
๋ณต์กํ์ง๋ง ์ข๋ ์ธ์ฌํ๊ฒ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ์ปจํธ๋กคํ๊ณ ์ถ๋ค๋ฉด, ์ง์ ์กฐ๊ฑด ๋ถ๊ธฐ๋ฅผ ํตํด ์ผ์ผํ ์ง์ ํด ์ค ์ ์๋ค.
์๋ฅผ ๋ค์ด ์ด๋ฒคํธ ์ ํ๋ฅผ ์ด์ฉํด html์ body์๋ง ์ด๋ฒคํธ๋ฅผ ๋ฑ๋กํ๊ณ , ์ด๋ ์์์ ์์ญ์ ํด๋ฆญ ํ๋๋ผ๋ ๋ฒ๋ธ๋ง์ ํตํด body์ ์ด๋ฒคํธ๊ฐ ํธ์ถ๋๊ฒ ๋๋๋ฐ, ์ด๋ ์ฝ๋ฐฑ ํจ์์ ๋งค๊ฐ๋ณ์ e (event) ๋ฅผ ์ด์ฉํด ํ์ฌ ํธ์ถ๋ ํ๊ฒ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ ๋น๊ตํจ์ผ๋ก์จ ์ ์ด๊ฐ ๊ฐ๋ฅํ ์๋ฆฌ์ด๋ค.
e.target ์ ์ค์ ์ด๋ฒคํธ๊ฐ ๊ฑธ๋ฆฐ DOM ์๋ฆฌ๋จผํธ ๊ฐ์ฒด์ด๊ณ , ๊ทธ ์์ tagName, clasName, id ์์ฑ์ ํตํด ํ๊ทธ์ ์ ๋ณด๋ฅผ ๋ถ๋ฅํ ์ ์๋ค.
document.body.addEventListener('click', (e) => {
if (e.target.id === "ancestor") {
print('ancestor')
}
if (e.target.id === "parent") {
print('parent')
}
if (e.target.id === "child") {
print('child')
}
});
See the Pen event bubbleing 6 by barzz12 (@inpaSkyrim) on CodePen.
๐ e.preventDefault()
e.preventDefault() ๋ ์ด๋ฒคํธ ์ ํ ๋ฟ๋ง ์๋๋ผ ๊ธฐ๋ณธ ์ด๋ฒคํธ ๋์ ์์ฒด๋ฅผ ์ทจ์ํ๋ค.
์๋ฅผ๋ค์ด <a href="url"> ์ ๋งํฌ ๊ธฐ๋ฅ์ด๋, <form> ํ๊ทธ์ submit ์ด๋ฒคํธ๋ฅผ ์ทจ์ํ ๋ ์ ์ฉํ๋ค.
์ง๊ธ๊น์ง ์ด๋ฒคํธ ๋์ ์ ์ด ํจ์์ ๋ํด ์ ๋ฆฌํด๋ณด์๋ฉด ์๋์ ๊ฐ์ด ๋๋ค.
- e.stopPropagation() : โ์ด๋ฒคํธ ์ ํ ์ค์ง
- e.stopImmediatePropagation() : ์ด๋ฒคํธ ์ ํ ์ค์ง + ํ์ ์ด๋ฒคํธ ์คํ ์ค์ง
- โe.preventDefault() : ์ด๋ฒคํธ ์ ํ ์ค์ง + ํ์ ์ด๋ฒคํธ ์คํ ์ค์ง + ์ด๋ฒคํธ ๊ธฐ๋ณธ ๋์ ์ค์ง
์ด๋ฒคํธ ์ ํ ๋ฐฉ์ง ์ฃผ์์
๋ฒ๋ธ๋ง ์ด๋ฒคํธ ์ ํ๋ฅผ ๋ง๋ e.stopPropagation() ๋ฉ์๋๋ ์ถํ์ ๋ฌธ์ ๊ฐ ๋ ์ ์๋ ์ํฉ์ ๋ง๋ค์ด๋ผ ์ ์๋ค๋ ์ ์ ์ ์ํด์ผ ํ๋ค.
์๋ฅผ๋ค์ด ๋ด ์๋น์ค์์ ์ฌ๋๋ค์ด ํ์ด์ง์ ์ด๋๋ฅผ ํด๋ฆญํ๋์ง ๋ฑ์ ํ๋ ํจํด์ ๋ถ์ํ๊ธฐ ์ํด, window ๋ด์์ ๋ฐ์ํ๋ ํด๋ฆญ ์ด๋ฒคํธ ์ ๋ถ๋ฅผ ๊ฐ์ง๋ ๋ถ์ ์์คํ
์ ์ฌ์ฉํ ๋, ์ด๋ฐ ๋ถ์ ์์คํ
์ ์ฝ๋๋ ํด๋ฆญ ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํ๊ธฐ ์ํด ๋ณดํต document.addEventListener('click') ์ ๊ฐ์ด ์ฌ์ฉํ๋๋ฐ, stopPropagation๋ก ๋ฒ๋ธ๋ง์ ๋ง์๋์ ์์ญ์์ '์ฃฝ์ ์์ญ(dead zone)'์ด ๋์ด๋ฆฌ๊ธฐ ๋๋ฌธ์ ๋ถ์์ด ์ ๋๋ก ๋์ง ์์ ์ ์๋ค.
๋ฐ๋ผ์ ๊ผญ ํ์ํ ๊ฒฝ์ฐ๋ฅผ ์ ์ธํ๊ณค ๋ฒ๋ธ๋ง์ ๋ง์ง ์๋ ๊ฒ์ด ์ข๋ค. ์ํคํ ์ฒ๋ฅผ ์ ๊ณ ๋ คํด ์ง์ง ๋ง์์ผ ํ๋ ์ํฉ์์๋ง ๋ฒ๋ธ๋ง์ ๋ง์์ผ ํ๋ค.
๋ง์ผ ๋ฒ๋ธ๋ง์ ๋ง์์ผ ํด๊ฒฐ๋ ๊ฒ ๊ฐ์ ๋ฌธ์ ๋ผ๋ฉด ์ปค์คํ ์ด๋ฒคํธ๋ฅผ ์ฌ์ฉํด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์๋ ์๋ค. ๋ํ ๊ฐ ์์์ ํธ๋ค๋ฌ์ event ๊ฐ์ฒด์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ค๋ฉด, event ๊ฐ์ฒด๋ ๋ค๋ฅธ ํธ๋ค๋ฌ์ ๊ณต์ ๋๊ธฐ ๋๋ฌธ์, ์๋ ์๋์ชฝ์์ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๋์ง๋ฅผ ๋ถ๋ชจ ์์์ ํธ๋ค๋ฌ์๊ฒ ์ ๋ฌํ ์ ์์ผ๋ฏ๋ก, ์ด ๋ฐฉ๋ฒ์ผ๋ก๋ ์ด๋ฒคํธ ์ ํ๋ฅผ ํต์ ํ ์ ์๋ค.
ancestor.addEventListener("click", (e) => {
e.target.customNum = 999;
print('ancestor');
}, true)
parent.addEventListener("click", (e) => {
e.target.customString = "hello";
print('parent');
}, true)
child.addEventListener("click", (e) => {
print('child' + e.target.customNum + e.target.customString)
})
์๋ ์บก์ฒ๋ง ์ด๋ฒคํธ ์ ํ ์ฝ๋์ธ๋ฐ, child ์์ญ์ ํด๋ฆญํ๋ค๋ฉด ๋จผ์ ancestor์ ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ํธ์ถ๋๊ณ e.target์ ์ถ๊ฐ ์ปค์คํ
์์ฑ์ผ๋ก customNum : 999 ๊ฐ์ ์ ์ฅํ๊ฒ ๋๊ณ , ๊ทธ๋ค์ parent์ ์ด๋ฒคํธ ๋ฆฌ์ค๋์์ customString : "hello" ๋ฅผ ๊ทธ๋ฆฌ๊ณ ๋ง์ง๋ง child์ ์ด๋ฒคํธ ๋ฆฌ์ค๋์์ ๊ณต์ ๋๋ event ๊ฐ์ฒด์ ๋ฑ๋กํ ์ปค์คํ
์์ฑ์ ๊ฐ์ ธ์ค๋ ์๋ฆฌ์ด๋ค.
# ์ฐธ๊ณ ์๋ฃ
https://developer.salesforce.com/blogs/developer-relations/2017/08/depth-look-lightning-component-events
https://ko.javascript.info/bubbling-and-capturing
https://poiemaweb.com/js-event