솔미는 성장중
[JS] 이벤트 (event) 본문
🎃 .addEventListener()
대상에 이벤트 청취(listen)을 등록.
대상에 지정한 이벤트가 발생했을 때 지정한 함수(Handler) 호출
ex) click, dbclick(더블클릭시), wheel, keydown, mousedown(버튼 누를때), mouseup(버튼 뗄때), mouseenter(포인터가 요소 위로 올라갈 때), mouseleave(포인터가 요소 밖으로 나올 때), mousemove(포인터가 움직일 때), contextmenu(우클릭했을 때) 등등..
click 예시)
childEl.addEventListener('click',() => {
childEl.classList.toggle('active') //actvie클래스 있으면 없애고, 없으면 만들고.
})
wheel 예시)
const el = document.querySelector('div')
el.addEventListener('wheel',event => {
console.log(event) //scroll관련 이벤트 정보 출력
})
keydown 예시)
const inputEl = document.querySelector('input')
inputEl.addEventListener('keydown',event => {
console.log(event.key) //input에 입력하는 값이 바로 console.log에 찍힘. enter, shift, esc 모두 가능.
})
mousedown & mouseup 예시)
childEl.addEventListener('mousedown',() => { //누를 때
childEl.classList.add('active')
})
childEl.addEventListener('mouseup',() => { //뗄 때
childEl.classList.remove('active')
})
mousemove 예시)
childEl.addEventListener('mousemove',event => {
console.log(event.offsetX, event.offsetY) //마우스 위치 출력
})
🎃 .removeEventListener()
대상에 등록했던 이벤트 청취 제거
이렇게 제거하려면 변수에다가 함수를 할당해서 사용해야 한다.
메모리 관리를 위해 제거하는 과정 필요하다.
🎃 이벤트 객체
대상에서 발생한 이벤트 정보를 담고 있다.
예시) HTML
<body>
<div class="parent">
<div class="child"></div>
</div>
</body>
JS
const parentEl = documnet.querySelector('.parent')
parentEl.addEventListener('click', event=> {
console.log(event.target, event.currentTarget)
//parent에 해당하는 부분 클릭 시 : parent클래스 div parent클래스 div
//child에 해당하는 부분 클릭 시 : child클래스 div parent클래스 div
console.log(event)
//PointerEvent{...} 이벤트에 대한 다양한 정보 출력
})
event.target : 이벤트가 발생한 해당 요소 (위 예시에선 클릭한 곳)
event.currentTarget : 이벤트가 등록된 요소
🎃 기본 동작 방지
event.preventDefault()
ex) 마우스 휠 스크롤 동작 방지
const parentEl = document.querySelector('.parent')
parentEl.addEventListener('wheel',event => {
event.preventDefault() //스크롤이 움직이지 않음.
})
ex) a태그 페이지 이동 방지도 가능
: a태그를 querySelector로 받아와서 click 이벤트에 event.preventDefault() 해주기
🎃 이벤트 버블(전파) 방지
이벤트 버블: 하위 요소에 인터랙션을 했는데, 상위요소에도 인터랙션이 입력되어 이벤트가 발생하는 상황
event.stopPropagation()
event.stopPropagation() //버블링 정지
예시)
HTML
<body>
<div class="parent">
<div class="child">
<a href="https://~~~">링크</a>
</div>
</div>
</body>
JS
const parentEl = document.querySelector('.parent')
const childEl = document.querySelector('.child')
const aEl = document.querySelector('a')
window.addEventListener('click',event => {
console.log("window");
})
document.body.addEventListener('click',event => {
console.log("body");
})
parentEl.addEventListener('click',event => {
console.log("parent");
event.stopPropagation() //여기서 버블링 정지!!!!!!!!!!!!!!!!!
})
childEl.addEventListener('click',event => {
console.log("child");
})
aEl.addEventListener('click',event => {
console.log("a");
})
//a태그 클릭 -> a child parent 순으로 출력
//parent 클래스 클릭 -> parent
//body 태그 클릭 -> body window
🎃 capture 옵션 - 캡처링
{capture:true}가 있으면 먼저 동작함.
capture 옵션이 여러 개면 상위부터 출력 (먼저 동작하니까)
window.addEventListener('click',event => {
console.log("window");
})
document.body.addEventListener('click',event => {
console.log("body");
},{capture:true}) //여기에 주목!!!!!!!!!!!!!!!!!!!!!!!
parentEl.addEventListener('click',event => {
console.log("parent");
})
childEl.addEventListener('click',event => {
console.log("child");
})
aEl.addEventListener('click',event => {
console.log("a");
})
//child 클릭시 -> body child parent window 순으로 출력
만약 위 예시에서 body의 클릭이벤트 내용으로 stopPropagation이 있다면?
body만 출력. 거기서 멈춘다.
캡처링 주의할 점)
addEventListener와 removeEventListener를 할 때 add 쪽에 {capture:true}옵션 추가해줬으면 remove쪽에도 추가해줘야 remove가 동작한다!
🎃 capture 옵션 - 핸들러 1번만 실행
{once: true}
parentEl.addEventListener('click',event => {
console.log("parent");
},{once: true})
🎃 capture 옵션 - 기본 동작과 핸들러 실행 분리
{passive: true}
둘의 실행을 분리시킴으로써 처리할 내용이 많아 핸들러 실행에 부하가 걸리는 상황이더라도 기본 동작은 부드럽게 작동할 수 있다.
parentEl.addEventListener('wheel',event => {
for(let i=0; i<10000; i+=1){ //부하가 걸리는 상황
console.log(i);
}
},{passive: true}) //분리
🎃 이벤트 위임 (Delegation)
비슷한 패턴의 여러 요소에서 이벤트를 핸들링해야하는 경우, 단일 조상 요소에서 제어하는 이벤트 위임 패턴을 사용.
parentEl.addEventListener('click',event => {
const childEl = event.target.closest('.child')
//parentEl내에 있는 child클래스인 애들 찾기(자기 자신 포함)
//event.target은 이벤트가 발생한 그 요소
if(childEl) {
console.log(childEl.textContent) //해당하는 child요소의 textContent 출력
}
})
🎃 Focus & Form Events
focus : 요소가 포커스가 됐을 때
blur : 요소가 포커스가 해제됐을 때
input : 값이 변경됐을 때
change : 상태가 변경됐을 때 ex)tab/enter키를 통해 focus상태이다가 해제
submit : 제출 버튼을 선택했을 때
// 새로고침 하는 것이 default. 이것을 방지하려면 event.preventDefault()
// html상에서 type="submit"을 써줘야 함.
reset : 리셋 버튼을 선택했을 때
// html상에서 type="reset"을 써줘야 함.
focus, blur, input 예시)
el.addEventListener('focus',() => {
formEl.classList.add('active')
})
el.addEventListener('blur',() => {
formEl.classList.remove('active')
})
inputEl.addEventListener('input',event => {
console.log(event.target.value) //input창에 글씨 쓰는대로 바로 출력
})
submit 예시)
🎃 디스패치(dispatch)
예시)
child1.addEventListener('click', event => {
//강제로 이벤트 발생
child2.dispatchEvent(new Event('click')) //child1클릭 시 child2의 click이벤트 강제 실행
child2.dispatchEvent(new Event('wheel')) //child1클릭 시 child2의 wheel이벤트 강제 실행
child2.dispatchEvent(new Event('keydown')) //child1클릭 시 child2의 keydown이벤트 강제 실행
})
child2.addEventListener('click',event => {
console.log("child2 click")
})
child2.addEventListener('wheel',event => {
console.log("child2 wheel")
})
child2.addEventListener('keydown',event => {
console.log("child2 keydown")
})
🎃 커스텀 이벤트
예시)
child1.addEventListener('hello-world', event => { //기존에 존재하지 않던 이벤트
console.log('성공!')
})
child2.addEventListener('click',event => {
child1.dispatchEvent(new Event('hello-world')} //강제 실행
})
데이터와 함께 커스텀 이벤트를 전달하고 싶다면? CustomEvent 클래스 사용해주기!
(단, 속성 이름은 detail만 가능!)
child1.addEventListener('hello-world', event => {
console.log('성공!')
console.log(event.detail) //123
})
child2.addEventListener('click',event => {
child1.dispatchEvent(new CustomEvent('hello-world', { //customevent 클래스 써주기
detail:123
})} //강제 실행
})
'JavaScript' 카테고리의 다른 글
[JS] 오픈 api 활용하기 (0) | 2023.08.06 |
---|---|
[JS] 기타 Web APIs (0) | 2023.08.04 |
[JS] DOM : 크기 & 좌표 구하기 (0) | 2023.08.02 |
[JS] 불변성 (0) | 2023.07.31 |
[JS] DOM (0) | 2023.07.31 |