Event flow
이벤트가 발생하면 capturing phase -> target phase -> bubbling phase 순으로 이벤트를 감지한다.
<div class="outer">
<div class="middle">
<button>Click Me</button>
</div>
</div>
const outer = document.querySelector('.outer');
const middle = document.querySelector('.middle');
const button = document.querySelector('button');
outer.addEventListener('click', event => {
console.log(`outer: ${event.currentTarget}, ${event.target}`);
});
// outer: [objectHTMLDivElement], [object HTMLButtonElement]
middle.addEventListener('click', event => {
console.log(`middle ${event.currentTarget}, ${event.target}`);
});
// middle: [objectHTMLDivElement], [object HTMLButtonElement]
button.addEventListener('click', event => {
console.log(`button1 ${event.currentTarget}, ${event.target}`);
});
// button: [objectHTMLButtonElement], [object HTMLButtonElement]
outer box 안에 middle box가 있고, middle box 안에 button이 있다.
3가지 요소에 각각 click event가 걸려있다.
button을 click하면 button -> middle -> outer 순으로 3가지 요소에서 모두 이벤트가 발생한다.
button을 누르면 부모요소에서 부터 button까지 event가 전달되고(capturing phase )
button에 등록된 event handler가 호출된다.(target phase)
그 다음 부모요소에 등록된 event handler를 호출하게 된다.(bubbling phase )
보통 capturing 단계에서 event를 처리하는 일은 흔하지 않다.
target.addEventListener(type, listener, [useCapture]);
event handler의 useCapture의 기본값은 false이다.
그래서 따로 지정을 해주지 않는 이상 capturing 단계에서는 event가 일어나지 않는다.
button은 event.currentTarget과 event.target이 동일하다.
하지만 outer와 middle은 event.currentTarget과 event.target이 다른 요소를 나타낸다.
event.currentTarget : 이벤트가 걸려있는 해당 요소를 리턴한다.
event.target : 이벤트가 발생한 요소, 사용자 클릭한 요소를 리턴한다.
outer과 middle의 event.currentTarget은 해당 요소인 div를 가리키고,
outer과 middle의 event.target은 이벤트를 발생시킨 button을 가리킨다.
내가 원하는 eventListener만 실행되도록 하려면 어떻게 해야할까?
stopPropagation(), stopImmediatePropagation()을 쓸 수도 있지만
위험하고 예상하지 못한 오류가 발생할 수 있으므로 가능하면 사용하지 않는 것이 좋다.
그러면??
조건이 만족할 때만 이벤트를 실행하도록 처리하면 된다.
즉, 부모 요소에서 event.currentTarget과 event.target이 동일하지 않으면
리턴을 해서 그 이벤트를 종료시킨다.
그러면 button을 클릭 했을 때는 button에 걸려있는 event만 실행된다.
const outer = document.querySelector('.outer');
const middle = document.querySelector('.middle');
const button = document.querySelector('button');
outer.addEventListener('click', event => {
if (event.target !== event.currentTarget) {
return;
}
console.log(`outer: ${event.currentTarget}, ${event.target}`);
});
// 실행되지 않음
middle.addEventListener('click', event => {
if (event.target !== event.currentTarget) {
return;
}
console.log(`middle ${event.currentTarget}, ${event.target}`);
});
// 실행되지 않음
button.addEventListener('click', event => {
console.log(`button1 ${event.currentTarget}, ${event.target}`);
});
// button: [objectHTMLButtonElement], [object HTMLButtonElement]
'JavaScript' 카테고리의 다른 글
[JS] Event delegation(이벤트 위임) (0) | 2021.01.25 |
---|---|
[JS] Object의 생성과 접근 & Constructor Function (0) | 2021.01.23 |
[JS] Class Ingeritance (클래스 상속) (0) | 2021.01.16 |
[JS] Class 선언과 Object 생성 (0) | 2021.01.16 |
[JS] JavaScript Function & Arrow Function (0) | 2021.01.15 |