그룹스터디 🦆 팀 러버덕과 함께!
< 목차 >
1.이벤트란?
2.이벤트 핸들러 등록
3.이벤트 종류
4.이벤트의 흐름
5.정리
이벤트란 브라우저상에서 일어나는 모든 일이다.
마우스 클릭을 하거나, 창을 줄이거나, 스크롤을 하거나 등등 브라우저상에서 일어나는 모든 일들을 이벤트라고한다.
개발자들은 이벤트를 잘 다루는 것이 매우 중요한데 어떤 이벤트를 먼저 실행시킬지, 특정이벤트가 발생하면 다른 이벤트는 동작하면 안되게하던지 등
이런 이벤트들을 다루는 것을 이벤트 핸들링이라고한다.
이벤트 발생 시, 이벤트 처리해주는 콜백함수를 이벤트 핸들러라고한다.
이벤트가 발생하면 이벤트 핸들러(콜백함수)가 호출되는데,
당연히 이벤트 핸들러를 등록을 해야 호출이 되는데 이벤트 핸들러 등록하는 방법에는 3가지가 있다.
1.HTML요소에 등록
2.DOM요소 프로퍼티에 등록
3.EventTarget 메서드 사용 (이벤트 리스너)
HTML태그에 이벤트 핸들러를 등록하는건데 간단하지만 추천하지않는다.
HTML태그와 JS코드는 분리해서 관리하는게 유지보수에 좋다.
<button onclick=showResult()>button</button>
<script>
function showResult(){
console.log('버튼 클릭!');
}
</script>
html과 js코드가 분리되서 작성할 수 있지만 하나의 요소에 하나의 이벤트만 등록할 수 있다는 단점이 있다.
<script>
const btn = document.querySelector('button');
btn.onclick=showResult();
</script>
EventTarget의 세 개의 메서드 중, addEventListener()가 있다.
모든 DOM요소들은 EventTarget의 상속을 받는다.
따라서 모든 DOM요소들은 EventTarget의 메서드를 사용할 수 있다.
EventTarget의 인터페이스(메서드)
mdn: https://developer.mozilla.org/ko/docs/Web/API/EventTarget
- addEventListener() : 이벤트 등록
- removeEventListener() : 이벤트 취소
- dispatchEvent()
addEventListener()로 등록한 콜백함수를 이벤스 리스너라고한다.
addEventListener()를 사용하면 하나의 요소에 여러 개의 이벤트를 등록할 수 있다.
addEventListener(이벤트 유형, 콜백함수, 이벤트 전파방식);
mdn : https://developer.mozilla.org/ko/docs/Web/API/EventTarget/addEventListener#%EA%B5%AC%EB%AC%B8
<script>
const btn = document.querySelector('button');
btn.addEventListener("click",()=>{console.log('btn1')});
btn.addEventListener('click',()=>{console.log("btn2')});
</script>
1,2번 방식에서는 이벤트 유형에 'on'을 붙여야하지만
이벤트리스너에서는 'on'을 붙이지 않는다.
키보드에관한 이벤트 : keyup,keydown,.....
마우스에관한 이벤트 : mousemove,mouseleave,.......
.
.
.
mdn참조 ) 이벤트 종류
https://developer.mozilla.org/ko/docs/Web/Events
브라우저가 어떻게 이벤트를 인지하는지 알아보자.
.png)
btn에 'clicl'이라는 이벤트를 등록하였다.
btn을 클릭하면 btn의 이벤트 핸들러가 호출될것이다.
하지만 만약 child에도 동일한 이벤트가 등록되었다면 무슨 일이 발생할까?
child이벤트핸들러 + btn이벤트핸들러가 호출된다.
이유는 이벤트 객체의 캡쳐링과 버블링 특징 때문이다.
mdn: 캡쳐링과 버블링 https://developer.mozilla.org/ko/docs/Learn/JavaScript/Building_blocks/Events#other_event_concepts
btn버튼을 누르면
1단계 : 캡쳐링)
최상위부모부터 해당 이벤트 발생한 시점까지 내려온다.
.png)
2단계 : 타깃)
캡쳐링으로 해당 이벤트요소에 도달한다. 이벤트 리스너는 이 시점에 실행된다.
3단계 : 버블링)
해당 이벤트 발생한 시점부터 최상위 부모까지 이벤트가 올라가게된다.
.png)
캡쳐링은 잘 다루지않고 버블링이 중요하다.
캡쳐링을 통해서 해당 이벤트인 btn까지 내려왔다면 이때 btn이벤트핸들러가 호출되고
다시 버블링을 통해 최상위 부모까지 이벤트가 도달하는데 이때 동일한 이벤트를 가진 부모의 이벤트핸들러도 호출된다.
즉, 버블링은 자식에게서 발생된 이벤트가 부모까지 전파되고 같은 이벤트를 가진 부모가 있으면 자동으로 이벤트 핸들러가 호출되고 이벤트는 계속 최상위 부모까지 올라가게 된다.
테스트)
부모,자식요소에도 btn과 똑같이 'click'이벤트 유형으로 이벤트를 등록하였다.
<script>
const parent = document.querySelector('.parent');
const child = document.querySelector('.child');
const btn = document.querySelector('button');
parent.addEventListener('click',()=>{console.log('I am parent')})
child.addEventListener('click',()=>{console.log('I am child')})
btn.addEventListener("click",()=>{console.log('I am button')})
</script>

결과는 버블링을 통해 'click'이라는 행동이 부모까지 전달되게되며
만약 부모에서 'click' 동작을 가진 이벤트가 있다면 부모 이벤트 콜백함수도 자동 발생된다.
(단,형제요소에서는 발생하지않고 오직 부모/자식 관계만 캡쳐링과 버블링이 발생한다.)
따라서 child,parent요소에'click'을 하지 않더라도 btn요소에 'click'동작이 발생하면 child,parent도 'click'동작을 받고 'click'이벤트가 있으면 콜백함수 호출된다.
내가 버블링 공부하면서 헷갈렸던 것)
💡 자식요소에 이벤트없고 부모한테만 있으면 버블링 효과가 있을까?
💡 자식요소에 이벤트있고 부모는 없으면 버블링 효과가 없을끼?
나는 자식요소에 이벤트 등록을 해야지만 그 이벤트가 버블링을 통해서 전달되는건가 헷갈렸고
부모에 이벤트가 없거나 'click'이벤트가 발생했는데 부모에는 'mousemove'이벤트를 등록했으면 버블링이 전달안되는건가 헷갈렸었다.
하지만 이벤트 버블링은 이벤트리스너와 무관하게 항상 발생한다.
자식,부모든 이벤트 여부를 떠나서 자식한테서 'click'이라는 동작을 했거나
'마우스 스크롤'을 했거나 '드래그'동작을 등을 했을때, 그 동작은 무조건 최상위 부모로 전달된다. 해당되는 '동작'이벤트를 가지고 있으면 반응을 할 것이고 없다면 반응하지않을것이다.
하지만 반응을 하든 안하든 이벤트는 무조건 전달된다.
즉, 항상 버블링을 일어난다.
버블링개념이 많이 사용되고 중요한 이유는 이벤트 위임이다.
이벤트 위임은 자식노드가 할 일을 부모노드가 대신하는 것이다.
<body>
<ul>
<li class="one">1</li>
<li class="two">2</li>
<li class="three">3</li>
<li class="four">4</li>
</ul>
</body>
<script>
const one= document.querySelector('.one');
const two= document.querySelector('.two');
const three= document.querySelector('.three');
const four= document.querySelector('.four');
one.addEventListener('click',()=>{console.log('one')})
two.addEventListener('click',()=>{console.log('two')})
three.addEventListener('click',()=>{console.log('three')})
four.addEventListener('click',()=>{console.log('four')})
</script>
각 자식요소마다 addEventListener()를 걸어주게 된다면 반응속도가 느려지게된다.
자식요소에 일일이 이벤트를 등록하는것보단 부모에 등록하는것이좋다.
<script>
const ul = document.querySelector('ul');
ul.addEventListener('click',(e)=>{
if(e.target.className ='one'){
console.log('one');
}
else if(e.target.className='two'){
console.log('two');
}
else if(e.target.className='three'){
console.log('three')
}
else if(e.target.className='four'){
console.log('four');
}
})
</script>
이렇게 이벤트 위임을 함으로써 각 자식요소마다 이벤트리스너를 등록하지않고 부모에게만 이벤트리스너를 등록해서 자식노드의 일을 부모노드가 대신 처리해준다.
이것이 가능한 이유는 버블링때문이다.
자식요소에서 '클릭'을 했다면, '클릭'이벤트가 부모까지 전달되기때문에 이벤트 위임이 가능하다.
이벤트에 대해서 알아봤다.
이벤트는 브라우저에서 일어나는 모든 일이고 이벤트를 사용하기 위해서는 이벤트 핸들러를 등록해야한다.이벤트 핸들러는 대게 addEventListener() 를 사용한다.
이벤트가 발생하기까지 어떤 과정을 거치는지도 알아봤다.
이벤트가 발생하기까지 캡쳐링단계를 거치고 타킷단계에 해당 이벤트 리스너가 실행되고 버블링단계를 거쳐서 최상위 부모까지 이벤트가 전달된다.
버블링을통해서 우리는 이벤트 위임을 할 수 있다.
이벤트 위임을 통해서 각 자식요소마다 이벤트를 등록 하는것이아닌, 자식에서 처리해야될 이벤트를 부모에서 대신 처리함으로써 이벤트리스너 중복을 피할 수 있고 성능을 개선 할 수 있다.
다음에는 이벤트 루프에대해서 알아보겠다.
여기까지는 이벤트 핸들러가 호출되기까지의 과정을 살펴보았고
다음에는 이벤트 핸들러가 호출되는 순간 JS엔진이 이벤트 핸들러를 어떻게 처리해서 최종적으로 사용자에게 보여지는지 알아보겠다.