이벤트
- 마우스 이벤트(click, mouseover, mouseout, mousemove...)
- 폼 요소 이벤트(submit, focus)
- 키보드 이벤트(keydown, keyup)
- 문서 이벤트
등의 DOM 이벤트 들이 있는데 이러한 이벤트가 발생했을 경우 실행되는 함수를 이벤트 핸들러라고 하며 핸들러를 할당하는 방법은 다양하다.
1. HTML 속성
HTMl 안의 onevent 속성에 이벤트 핸들러 할당하는 방법
Ex. <h1 onclick="실행코드"> 등
간단한 코드는 그냥 작성하기도 하지만 코드가 같다면 별도의 함수를 만들고 이를 호출한다.
<button onclick="alert('클릭했네?');">클릭해보세요</button>
<button onmouseover="mouseover(this);">마우스를 올려보세요</button>
<script>
function mouseover(elem){
alert('마우스 올리지마세요!');
console.log(elem);
console.log(elem.innerHTML);
elem.innerHTML = '마우스 올리지 마세요@';
}
</script>
핸들러 내부에 쓰인 this의 값은 핸들러가 할당된 요소 => 이벤트가 발생한 button
2. DOM 프로퍼티
요소 객체가 가지고 있는 onevent 속성에 이벤트 핸들러를 연결하는 방법
Ex. element.onclick = 이벤트핸들러(함수);
해당 프로퍼티는 하나밖에 없기 때문에 여러 개의 이벤트를 할당할 수는 없다.
만약 이벤트 객체를 제거할 때에는 속성 값에 null을 넣어주면 된다.
<button id="test1">test1 실행확인</button>
<button id="test2">test2 실행확인</button>
<div id="area1" class="area"></div>
<script>
let test1 = document.getElementById('test1');
let test2 = document.getElementById('test2');
test1.onclick = function() {
document.getElementById('area1').innerHTML
+= 'test1이 실행되었습니다.<br>';
//핸들러 내부에 쓰인 this의 값은 핸들러가 할당된 요소
//=> 이벤트가 발생한 버튼
console.log(this);
};
test1.onclick = () => alert('이벤트 덮어쓰기!');
이전 이벤트 핸들러는 무시된다 => 하나의 이벤트 밖에 연결할 수 없음
function removeEvent() {
document.getElementById('area1').innerHTML
+= "test2가 실행되면서 test1 이벤트 제거<br>";
test1.onclick = null;
}
//선언되어 있는 함수를 핸들러에 할당함
test2.onclick = removeEvent;
test1실행확인을 누르면 더이상 작동하지 않는다. (test2실행확인 누르면서 test1제거됨)
3. addEventListener
- 1, 2번 방식의 이벤트 핸들러 할당의 경우 복수의 핸들러 할당 불가
element.addEventListener(event, handler, [options])
element.removeEventListener(event, handler, [options])
- 위의 메소드로 핸들러를 추가/삭제하면서 복수의 핸들러를 할당할 수 있다.
let btn = document.querySelector("#btn");
//복수의 이벤트 핸들러 할당 가능
btn.addEventListener('click', () => alert('첫 번째 이벤트 동작!'));
btn.addEventListener('click', () => btn.style.background = 'red');
실행확인 버튼을 누르면 alert구문 수행
alert창을 닫으면 실행확인 버튼이 빨간색으로 변했다.
- 핸들러를 삭제하려면 핸들러 할당시 사용한 함수를 그대로 전달해야 하므로 위와 같은 경우는 삭제 불가
- 함수 선언하여 핸들러 할당해서 삭제해보기
function myFunction(){
alert('곧 삭제될 친구!');
}
btn.addEventListener('mouseover', myFunction);
실행확인 버튼에 마우스오버하면 alert가 뜬다.
마우스오버하면 아무것도 실행되지않는다. (삭제테스트)
btn.removeEventListener('mouseover', myFunction);
이벤트 객체
- 이벤트 객체는 이벤트에 대한 상세한 정보 (눌린 키보드 키, 마우스 클릭된 좌표 등)를 가지고 있다.
- 이벤트가 발생하면 브라우저는 이벤트 객체를 만들어 핸들러에 인수 형태로 전달한다.
- 핸들러 내부에서 이벤트 타입과 요소 이벤트가 발생한 좌표 등을 확인할 수 있다.
<button id="evtObj">이벤트 객체 확인</button>
<script>
let evtObj = document.querySelector("#evtObj");
evtObj.onclick = function(event){
console.log(event);
console.log(event.type + " 이벤트");
console.log(event.currentTarget);
console.log("에서 발생");
console.log("이벤트가 발생한 곳의 좌표는 ");
console.log(event.clientX + " : " + event.clientX);
};
</script>
- HTML 속성 안에서도 event 객체 사용 가능
<button onclick="console.log(event);">이벤트 객체 확인</button>
script에서는 파라미터를 event든, evt든 다른 이름으로 해도 되는데
HTML 구문 안에서는 꼭 event라고 파라미터를 전달해줘야한다.
버블링과 캡쳐링
- 버블링이란 한 요소에 이벤트가 발생하면 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 동작하는 것
- 가장 최상단의 조상 요소를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작한다.
<div onclick="alert('1번 div');" class="div-test div1">
<div onclick="alert('2번 div');" class="div-test div2">
<div onclick="alert('3번 div');" class="div-test div3">
<div onclick="alert('4번 div');" class="div-test div4"></div>
</div>
</div>
</div>
제일 안쪽에 있는 파란색을 누르면
4번, 3번, 2번, 1번.. 뜬다. 초록색을 누르면 3번부터 1번까지 최상단의 조상 요소를 다 출력한다.
이에 대한 것을 막기위해 밑에서 버블링 막는 함수를 작성해보자.
이벤트 버블링 막기
event.target : 실제 이벤트가 시작된 타깃 요소로 버블링이 진행되어도 변함이 없음
event.currentTarget : 현재 실행 중인 핸들러가 할당된 요소를 의미
이벤트 객체의 메소드 event.stopPropagation()을 사용하면 버블링 중단을 명령함
<div onclick="bubble(event);" class="div-test div1">
<div onclick="bubble(event);" class="div-test div2">
<div onclick="bubble(event);" class="div-test div3">
<div onclick="bubble(event);" class="div-test div4"></div>
</div>
</div>
</div>
<script>
function bubble(event){
console.log("event.target");
console.log(event.target);
console.log("event.currentTarget");
console.log(event.currentTarget);
}
</script>
제일 안에 있는 파란색을 눌러보니
target은 4, currentTarget도 4
target 4, current3
target 4, current2
target 4, current1
이런식으로 출력된 것을 확인할 수 있다.
이런 버블링을 막는 stopPropagation()을 써주자.
<script>
function bubble(event){
console.log("event.target");
console.log(event.target);
console.log("event.currentTarget");
console.log(event.currentTarget);
//버블링 막기
event.stopPropagation();
}
</script>
이벤트 캡쳐링
캡처링 : 이벤트가 하위 요소로 전파
버블링 : 이벤트가 상위 요소로 전파
캡처링 단계에서 이벤트를 잡아내려면 addEventListener의 capture 옵셩을 true로 설정
<div class="div-test div1 capture">
<div class="div-test div2 capture">
<div class="div-test div3 capture">
<div class="div-test div4 capture"></div>
</div>
</div>
</div>
<script>
let divs = document.querySelectorAll(".capture");
console.log(divs);
divs.forEach(function(item){
console.log(item);
item.addEventListener('click', () => alert('캡쳐링 : ' + item.className), true);
item.addEventListener('click', () => alert('버블링 : ' + item.className));
});
</script>
파란색박스(div4)를 누르면
캡쳐링은 div1부터 먼저 alert되어 1, 2, 3, 4가 나오고
캡쳐링 출력이 끝나면 버블링 div4 부터 4, 3, 2, 1이 나온다.
기본 이벤트의 제거
기본 이벤트란
- a태그를 통한 페이지 이동
- submit 시 입력 양식 제출 후 페이지 갱신 등의 브라우저 기본 동작을 말함
태그에 기본적으로 설정 되어 있는 이벤트를 제거하는 방법은
1. event.preventDefault()
2. onevent를 통해 할당된 이벤트 핸들러의 return 값을 false로 반환
<a href="14_BOM.html" onclick="event.preventDefault()">클릭해도 절대 이동할 수 없는 a 태그</a>
비밀번호/비밀번호 확인
<form onsubmit="return invalidate();">
<label for="password">비밀번호 : </label>
<input type="password" name="password" id="password" required>
<br>
<label for="checkPwd">비밀번호 확인 : </label>
<input type="password" name="checkPwd" id="checkPwd" required>
<input type="submit" value="제출">
</form>
else구문에서 select()를 써주면 입력 후 드래그된 상태가 된다.
return false로 submit되지 않도록 한다.
<script>
function invalidate(){
let pwd1 = document.getElementById('password').value;
let pwd2 = document.getElementById('checkPwd').value;
if(pwd1 == pwd2){
alert('입력 비밀번호가 일치합니다');
}else{
alert('입력 비밀번호가 일치하지 않습니다');
document.getElementById('checkPwd').select();
return false;
}
}
</script>
'TIL > JavaScript' 카테고리의 다른 글
[JavaScript] 폼 이벤트 (0) | 2022.02.23 |
---|---|
[JavaScript] 마우스 이벤트, 키보드와 스크롤 이벤트 (0) | 2022.02.22 |
[JavaScript] BOM(Browser Object Model) (0) | 2022.02.21 |
[JavaScript] 문서 수정 (0) | 2022.02.21 |
[JavaScript] 요소 검색 (0) | 2022.02.21 |