이벤트 핸들러 등록 방법
- dom요소에 접근 후, onclick 프로퍼티를 준다.
- html태그에 onclick속성을 준다.
- addEventListener를 통해 이벤트를 등록한다.
1. dom요소에 접근 후, onclick 프로퍼티를 준다.
const btn = document.querySelector('.login-btn');
btn.onclick = function(){
console.log("login");
}
- 이 경우, 기존 onclick프로퍼티에 있던 값을 덮어쓴다.
- 기존값을 그대로 두고 추가만 하는 방법은 3번이고, 아래와 같다.(가장 권장되는 방법임!)
3. addEventListener를 통해 이벤트를 등록한다.
function login(){
console.log("login");
}
btn.addEventListener('click', login); // 클릭 이벤트 등록
btn.removeEventListener('click', login); // 클릭 이벤트 삭제
- removeEventListener 를 할 때에는 addEventListener를 할 때 썼던 참조값을 똑같이 써야 삭제된다.
function login(){
console.log("login");
}
btn.addEventListener('click', login);
btn.removeEventListener('click', login); // 삭제된다.
btn.addEventListener('click',function(){console.log("Hi")});
btn.removeEventListener('click',function(){console.log("Hi")}); // 삭제되지 않는다.
- 이벤트를 전달할 때에는 함수 명만을 전달해야한다.
btn.addEventListener('click', login); // 정상동작
btn.addEventListener('click', login()); // login함수는 return값이 없으므로 undefined가 넘겨진다.
이벤트 객체
이벤트 핸들러가 되는 함수의 첫번째 파라미터는 무조건 이벤트 객체이다.
모든 이벤트객체들은 타입과 상관없이 아래의 프로퍼티를 공통적으로 가진다.
- type : 이벤트 이름. click, mouseup, keydown 등.
- target : 이벤트가 발생한 요소.
- currentTarget : 이벤트 핸들러가 등록된 요소
- timeStamp : 이벤트 발생 시각(페이지가 로드된 이후부터 경과한 밀리초)
- bubbles : 버블링 단계인지를 판단하는 값
이벤트 버블링
- 한 요소에서 이벤트가 발생할 경우, 같은 타입의 이벤트에 한해서 부모의 이벤트, 부모의 부모이벤트.... window객체까지 이벤트를 실행한다.
- 현재요소 이벤트 실행 > 부모요소 이벤트 실행 > 부모의 부모요소 이벤트 실행 >.....> window객체를 만날때 까지 모든 이벤트를 순서대로 실행한다.
- target은 이벤트가 실행된 지점을 나타내기때문에 현재요소에서도, 부모요소에서도 같은 값을 출력한다.
- currentTarget은 이벤트사 실행된 요소를 출력하기때문에 현재요소에서는 현재요소를, 부모요소에서는 부모요소를 출력한다.
버블링 멈추기
element.stopPropagation();
- 버블링을 막으면 타겟요소의 이벤트만 발생하고, 부모요소의 이벤트들은 발생하지 않는다.
- 하지만 권장되지 않는다.
- 왜냐면 상위요소에 등록되어있는 이벤트가 버블링이 막힌 내부요소의 범위만큼 동작하지 못하게 되기 때문이다.
이벤트 캡처링
자주 쓰이진 않는다.
먼저 표준 dom이벤트에서 정의한 이벤트 흐름의 3단계는 다음과 같다.
- 캡처링 단계 : 이벤트가 하위 요소로 전파되는 단계
- 타깃 단계 : 이벤트가 실제 타깃 요소에 전달되는 단계
- 버블링 단계 : 이벤트가 상위 요소로 전파되는 단계
- 캡처링 단계에서 이벤트를 발생시키고 싶다면, addEventListner를 할 때에 세번째 파라미터로 "true" 또는 "{capture:true}" 를 전달하면 된다.
element.addEventListener('click', login, true);
// 또는
element.addEventListener('click', login, {capture: true});
이벤트 위임
- 자식요소에서 발생하는 이벤트를 부모요소에서 다루는 것을 이벤트 위임이라고 한다.
- 자식요소의 이벤트를 부모요소에 위임했다고 보면 된다.
- 이벤트 위임은 버블링을 이용한 것이기 때문에 자식요소에서 버블링을 (stopPropagation을 통해) 막아놓는다면 이벤트가 발생하지않는다.
// html 부분
<body>
<ul id="list">
<li class="item">밥먹기</li>
<li class="item">운동하기</li>
<li class="item">청소하기</li>
</ul>
</body>
// javaScript 부분
const list = document.querySelector('#list');
list.addEventListener('click', function(e){
e.target.classList.toggle('done');
});
const li = document.createElement('li');
li.classList.add('item');
li.textContent = '일기 쓰기';
list.append(li);
- 위와같은 코드에서, 각각의 li들을 클릭했을 때 이벤트를 발생시키고 싶은 것인데, "list" 라는 부모요소에 이벤트 핸들러를 등록시켰다.
- 원래라면 li들에 for문을 통해 이벤트를 등록시켰을텐데 그러지 않았다는 뜻임.
- 그런데 위와같이 작성할 경우, list에 포함되지만 li에는 포함되지 않는 여백을 클릭한 경우에도 이벤트가 발생한다.
따라서 아래와같이 수정한다.
const list = document.querySelector('#list');
list.addEventListener('click', function(e){
// 아래의 if문을 추가했다.
if(e.target.calssList.contains('item')){
e.target.classList.toggle('done');
}
});
const li = document.createElement('li');
li.classList.add('item');
li.textContent = '일기 쓰기';
list.append(li);
- 타겟의 classList에 "item"이 포함되어있는지 확인 후, 작업하도록 추가했다.
- 추가적으로, e.target.tagName은 태그를 대문자로 가지고있다고 한다.
브라우저의 기본 이벤트 동작
- a태그는 href속성의 값으로 이동하는 기본 동작을 한다.
- input태그는 포커스가 가능하고, 포커스된 채로 키보드를 누를경우 값이 입력되는 기본동작을 한다.
- 이러한 기본동작을 막는 방법은 다음과 같다.
aLink.addEventListener('click', function(e){
e.preventDefault();
alert('지금은 이동할 수 없습니다.');
})
- preventDefault사용이 권장되지는 않는다. 꼭 필요한 부분에만 사용해야한다.
마우스 버튼 이벤트
mouseEvent의 타입 몇가지
- mousemove : 마우스 포인터가 이동할 때
- mouseover : 마우스 포인터가 요소 밖에서 안으로 이동할 때
- mouseout : 마우스 포인터가 요소 안에서 밖으로 이동할 때
- mouseenter : 마우스 포인터가 요소 밖에서 안으로 이동할 때(버블링 발생X)
- mouseleave : 마우스 포인터가 요소 안에서 밖으로 이동할 때(버블링 발생X)
자식요소까지 영향을 끼치게 하고 싶은 경우에는 mouseover/mouseout을 사용하고,
자식요소에는 영향을 끼치지 않고 해당요소에서만 이벤트 핸들러를 다루고자 한다면 mouseenter/mouseleave 를 사용하면 되겠다.
mouseEvent의 property 몇 가지
- mouseEvent.clientX, clientY : 화면에 표시되는 창을 기준으로 마우스 포인터의 위치를 알 수 있다(마우스를 고정한채 위아래 스크롤을 할 경우, 같은 값을 출력한다.)
- mouseEvent.pageX, pageY : 웹문서 전체를 기준으로 마우스 포인터의 위치를 알 수 있다.(마우스를 고정한채 스크롤을 해도 다른 값을 얻는다.)
- mouseEvent.offsetX, offsetY : 이벤트가 발생한 요소(e.target)를 기준으로 마우스 포인터의 위치를 알 수 있다.
- mouseEvent.relatedTarget : 이벤트가 발생하기 직전(또는 직후)에 마우스가 위치해 있던 요소를 출력한다.
키보드이벤트
키보드 이벤트의 타입 몇가지
- keydown : 키보드를 누르는 순간 이벤트가 발생. (권장된다.)
- keypress : 키보드를 누르는 순간 이벤트가 발생하지만 출력값에 변화를 일으키는 키에만 이벤트가 발생한다.(esc나 control 등에는 반응 없고 키 하나를 꾹 누르고 있어도 이벤트는 한번만 인식한다. 또한 영어가 아니면 인식하지 못하는 등의 문제가 있기 때문에 웹 표준에서는 권장하지 않는다.)
- keyup : 키보드를 눌렀다가 뗀 순간 이벤트가 발생.
키보드 이벤트의 property 몇 가지
- keyboardEvent.key : 이벤트가 발생할 때 누른 키보드 값
- keyboardEvent.code : 이벤트가 발생할 때 누른 키의 키보드에서 물리적인 위치
input태그의 이벤트 타입 몇가지
- focusin : 포커스 되었을 때 이벤트가 발생
- focusout : 포커스가 빠져나갈 때 이벤트가 발생
- focus : 포커스 되었을 때 이벤트가 발생(버블링X)
- blur : 포커스가 빠져나갈 때 이벤트가 발생(버블링X)
- input : 사용자가 입력을 할 때 이벤트가 발생(처음 입력한 경우만을 의미)
- change : 요소의 값이 변했을 때 이벤트가 발생(처음 값과 입력이 끝난 후의 값이 변했을 때에만 발생)
- input에 포커스를 시켜놓고 엔터를 누르면, 입력이 끝났다는 것을 의미하기때문에 포커스를 잃지 않고 change이벤트를 발생시킬 수 있다.
scroll이벤트
- 보통 window객체에 scroll이벤트를 설정한다.
- window객체의 property를 활용해 사용할 수도 있는데 아래와 같이 사용가능하다.
let lastScrollY = 0;
function onSroll() {
const nav = document.querySelector('#nav');
const toTop = document.querySelector('#to-top');
const STANDARD = 30;
if (window.scrollY > STANDARD) { // 스크롤이 30px을 넘었을 때
nav.classList.add('shadow');
toTop.classList.add('show');
} else { // 스크롤이 30px을 넘지 않을 때
nav.classList.remove('shadow');
toTop.classList.remove('show');
}
if (window.scrollY > lastScrollY) { // 스크롤 방향이 아랫쪽 일 때
nav.classList.add('lift-up');
} else { // 스크롤 방향이 윗쪽 일 때
nav.classList.remove('lift-up');
}
lastScrollY = window.scrollY;
}
window.addEventListener('scroll', onSroll);
- 스크롤이 30px을 넘었을 때와 넘지 않았을 때를 구분할 수 있고
- 스크롤이 아래방향을 향하고 있는지, 윗 방향을 향하고 있는지 구분할 수 있다.
'JavaScript' 카테고리의 다른 글
JavaScript - HTTP 메소드 (0) | 2023.10.07 |
---|---|
JavaScript - this (1) | 2023.10.07 |
JavaScript - 노드 선택 (0) | 2023.10.03 |
JavaScript - 변수, 자료형 등 기본 문법 (1) | 2023.10.02 |
JavaScript - 브라우저의 동작 원리 (0) | 2023.10.01 |