javascript - Event

JM·2022년 3월 22일
0
post-thumbnail

codeit 을 통해 공부하고 정리한 내용입니다!
함부로 내용을 가져가서 사용하면 안 됩니다.

학원 마치고 집 와서 인강으로 계속 들으려니까.. 약간 피곤하기도 하다.ㅠㅠ
밥 먹고 쉬다가.. 한 시간 정도 늦게 공부를 시작했다.😭

조금씩 진도나가는게 느려지고 있다. 게으른게 아니라 내용이 조금씩 어려워지고있다!!


이벤트 핸들러 등록하기

  • click 이벤트 외에 마우스 이벤트/ 키보드 이벤트/ 포커스 이벤트/ 입력 이벤트/ 스크롤 이벤트/ 윈도우 창 이벤트가 있다.
  • removeEventListener 메소드는 파라미터로 전달하는 타입과 이벤트 핸들러가 addEventListener 메소드로 등록할 때와 동일 할 때만 이벤트 핸들러를 삭제할 수 있다.
// DOM 에 접근하는 방법
let btn = document.querySelector('#myBtn');

btn.onclick = function(){
	console.log('Hi Codeit!');
}

// 이벤트 핸들러 등록하기
function event1(){
	console.log('Hi Codeit!');
}

function event2(){
	console.log('Hi again!');
}

// elem.addEventListener(even, handler)
btn.addEventListener('click', event1);
btn.addEventListener('click', event2);

// elem.removeEventListener(ene, handler)
// 이벤트를 제거하기 위해서는 외부에서 함수를 작성해야한다.
btn.removeEventListener('click', event2);

// 이렇게 작성을 할 수 있지만 제거하기 위해서는 위에서 처럼 외부에서 함수를 작성해야한다.
btn.addEnventListener('click', function(){
	console.log('event3!;);
}
   
// 이렇게 작성하면 안 지워진다!! 의미 없는 코드가 된다.
btn.removeEventListener('click', function() {
  console.log('click!');
});
const btn = document.querySelector('#btn');

function printBtn() {
  console.log(btn.outerHTML);
}
  
btn.onclick = function() {
  console.log('click!');
};
btn.onclick = printBtn;	// 이렇게 사용하면 안된다!!!
btn.removeEventListener('click', printBtn); // 삭제 안됨 x

이벤트 객체

아래는 공통 프로퍼티!

  • type: 이벤트 이름 ('click', 'mouseup', 'keydown' 등)
  • target: 이벤트가 발생한 요소
  • currentTarget: 이벤트 핸들러가 등록된 요소
  • timeStamp: 이벤트 발생 시각(페이지가 로드된 이후부터 경과한 밀리초)
  • bubbles: 버블링 단계인지를 판단하는 값
const myInput = document.querySelector('#myInput');
const myBtn = document.quertSelector('#myBtn');

function printEvent(event){
	console.log(event);
}

myInput.addEventListener('keydown', printEvent);
myBtn.addEventListener('click', printEvent);

이벤트 핸들러 예제 01

for of 와 for in 이 헷갈린다.

const toDoList = document.querySelector('#to-do-list');
const items = toDoList.children;

// 내가 작성한 부분
for (let i = 0; i < 3; i++){
  items[i].addEventListener('click', updateToDo);
}

// 모범 답안
for (let item of items) {
  item.addEventListener('click', updateToDo);
}

이벤트 버블링

  • 같은 타입의 부모 요소에서부터 window 객체에 도달할 때까지 이벤트가 ㅂ라생한다.
  • 이벤트 버블링이 발생해도 이벤트.target처음 실행된 부분을 나타내주고 있다.
  • 이벤트 핸들러가 등록된 요소에 접근하기 위해서는 이벤트.currentTarget 으로 접근해야한다.
  • e.stopPropagation();을 사용하면 버블링을 멈출 수 있다

캡쳐링(capturing)

  • 캡쳐링 단계: 이벤트 요소가 최상단 window 객체에서부터 하위 요소로 전파되는 단계
  • 캡쳐링 단계에서 이벤트를 발생시켜야 하는 일은 매우 드문 경우라고 한다.
  • 보통 target 에 등록된 이벤트 핸들러가 동작하고 버블링 단계에서 부모 요소에 등록된 이벤트 핸들러를 작동 하는 것이 일반적이다.
// arrow function으로 함수 표현을 간략하게 바꾼 것이라고 한다.
 for (let elem of document.querySelectorAll('*')) {
      elem.addEventListener("click", e => alert(`캡쳐링 단계: ${elem.tagName}`), true);
      elem.addEventListener("click", e => alert(`버블링 단계: ${elem.tagName}`));
    }

이벤트 버블링 퀴즈

  • 이 부분은 약간 이해가 안 되서 작성해본다.

main의 이벤트가 코드에서 먼저 실행되고 출력되는게 맞다고 생각했는데..
이게 currentTarget 이라는 메소드 때문인 것인지 자식 요소들의 이벤트를 먼저 출력하는데 이유를 모르겠따.

자식 노드의 이벤트가 없기 때문에 자식 노드를 클릭하면 부모 노드 이벤트가 발생하는 이벤트 버블링 현상이 일어나는데 까지는 이해가된다. 그런데 여기서 왜 자식 노드에서 부모 노드의 이벤트가 발생하는 것일까? 무엇인가 놓치고 있는 기분이 든다.

const main = document.querySelector('#main');
const toDoList = main.lastElementChild;

function printCurrentTarget(event) {
  console.log(event.currentTarget);
}

main.addEventListener('click', printCurrentTarget);	// <= 먼저 이벤트가 발생하는데

for (let child of toDoList.children) {	// <= 이 친구들이 먼저 출력이된다.
  child.addEventListener('click', printCurrentTarget);
}

이벤트 위임(Event Delegation)

아래와 같이 작성하면 기존의 리스트 들은 이벤트가 작동하지만 새로 추가되는 리스트는 이벤트가 작동이 안되는 것을 확인할 수 있다.

const list = document.querySelector('#list');

for (let item of list.children){
	item.addEventListener('click', function(e){
    	e.target.classList.toggle('done');
    }
}
                          
const li = document.createElement('li');
li.classList.add('item');
li.textContent = '일기쓰기';
list.append(li);

위와 같은 문제를 해결하기 위해서는 자식 노드 하나씩 이벤트를 주는 것이 아니라 부모 요소에서 이벤트를 다루게 하면 된다.(위임했다고 보면 된다)

list.addEventListener('click', function(e){
	e.target.classList.toggle('done');
})

위의 해결방법도 불안전하다. 자식 요소를 제외한 부모인 요소를 선택해도 이벤트 핸들러가 작동한다. 아래와 같이 if 문을 추가해서 작성을 하면 된다.

list.addEventListener('click', function(e){
	if (e.target.classList.contains('item'){
    	e.target.classList.toggle('done');
    }
}

브라우저 기본 동작

  • event.preventDefault(): 기본 동작을 막는다.
  • 브라우저의 기본 동작을 막는 일이기 때문에 꼭 필요한 경우에만 사용하자.
const link = document.querySelector('#link');
const checkbox = document.querySelector('#checkbox');
const inputs = document.querySelector('#input');

// event.preventDefault
link.addEventListener('click', function(e){
	e.preventDefault();
  	alert('지금은 클릭 할 수 없습니다.');
}

inputs.addEventListener('keydown', funtion(e) {
	if (!checkbox.checked){
    	a.preventDefault();
      	alert('체크박스를 먼저 클릭해 주세요');
    }
})

profile
초조해하지 말자! 나는 충분히 할 수 있다! 인생은 길다!

0개의 댓글

관련 채용 정보