브라우저 이벤트
addEventListener('event', handler함수);
+ 마우스 이벤트 blur : 마우스가 떠났을 때 이벤트 발생
DOM프로퍼티를 통한 이벤트 설정
<핸들러 함수에 이벤트 정의>
function handler() {
console.log('클릭 이벤트 발생');
}
first.onclick = handler; // 온클릭 속성에게 핸들러 함수를 전달 실행X
first라는 dom 변수의 onclick 속성에다가 handler함수를 실행하지 않고 전달하면,
해당 이벤트가 실행될 때마다 handler 함수가 실행된다.
>>제거하고 싶다면, onclick = '' null 값을 할당한다.
addEventListener : 이벤트 설정
node.addEventListener(evet, handler함수, [options]);
removeEventListner : 이벤트 제거
node.removeEvnetListner(event, handler함수, [options]);
DOM, HTML(onclick) 에 직접 이벤트를 거는 것은 하나씩 밖에 걸 수 없고 복수의 이벤트는 걸 수 없다.
따라서 addEventListner를 사용하여 이벤트를 거는 것이 가장 좋은 방법이다.
<이벤트 추가하기>
function handler() {
console.log('클릭 이벤트 발생');
}
// 3. 메서드 : element.addEventListener(event, handler[, phase])
first.addEventListener('click', handler);
<이벤트 삭제하기>
핸들러를 삭제하려면 만들때 썼던 동일한 handler 함수를 전달해야 합니다.
getNode('.deleteEvent').addEventListener('click', ()=> {
first.removeEventListener('click', handler);
} )
삭제하기 버튼에 deleteEvent 클래스를 주어 'handler'이벤트를 remove 해준다.
<node 부터 이벤트 생성까지 하나의 함수로 관리>
function bindEvent(node,type,handler){
if(typeof node === 'string') node = getNode(node);
node.addEventListener(type,handler);
return () => node.removeEventListener(type, handler);
//값을 리턴할 때 삭제하는 함수를 내보내고 있다.
}
const remove = bindEvent('.first','click',handler);
getNode('.deleteEvent').addEventListener('click', remove);
클로저는 안쪽함수가 바깥쪽함수를 참조할 수 있으므로,
직접 이벤트를 받지 않아도 위의 환경을 기억하고있기 때문에 바로 함수를 진행시킬 수 있다.
onDomContentLoaded : 모든 요소가 다 로딩이 되었을 때를 체크
이벤트 객체 : 이벤트 할 때 발생하는 객체, 브라우저가 알아서 제공
e,prevetDefault() : e라는 이벤트 객체의 기본 메서드를 사용한다.
let handleBall = (e) => {
const {offsetX:x, offsetY:y} = e; //객제 구조 분해 할당
console.log(x, y);
}
e 객체 구조분해 할당 진행하여, 마우스 좌표값을 구하는 offsetX, offsetY를 각각의 알리아스에 넣어준다.
<중요 ★★★>
let handleBall = ({offsetX:x, offsetY:y}) => {
console.log(x, y);
}
ground.addEventListener('click', handleBall);
매개변수에서 바로 e 객체의 필요한 값만 구조할당을 받아주는 이 형태, react에서 가장 자주 나온다!!!!!!!!!!!!!
매우 중요하니 꼭 익숙해질 것!!!
<축구공 좌표 이동 실습>
<js>
const ground = getNode('.ground');
const ball = getNode('#ball');
let handleBall = ({offsetX:x, offsetY:y}) => {
console.log(x, y);
ball.style.transform = `translate(${x}px, ${y}px)`;
}
ground.addEventListener('click', handleBall);
+ 마우스 커서가 공의 중앙에 오도록
const ground = getNode('.ground');
const ball = getNode('#ball');
let handleBall = ({offsetX:x, offsetY:y}) => { //offsetWidth /2, offset
console.log(x, y);
ball.style.transform = `translate(${x - (ball.offsetWidth / 2)}px, ${y - (ball.offsetHeight / 2)}px)`;
}
ground.addEventListener('click', handleBall);
offsetWidth와 offsetHeight를 사용하면 된다.
<css>
#ball {
pointer-events: none;
}
더블 클릭해도 이벤트가 망가지지않도록 설계
debounce 함수
이벤트가 계속 실행되는 것을 막기 위해 timeout을 주고 callback 시켜주는 함수
function debounce(callback,limit){
let timeout;
return function (e){
clearTimeout(timeout);
timeout = setTimeout(() => {
callback.call(this,e)
}, limit);
}
}
// call, apply, bind
ground.addEventListener('mousemove',debounce(function(e){
console.log(this);
},1000))
ground.addEventListener('mousemove',debounce())
ㄴ 원래 addEventListener 함수 실행할 때 이름만 전달하는데, debounce() 함수를 실행시키면서 전달시켰다는 것은
안쪽 함수 function에 이벤트객체 'e'가 전달 된다는 뜻이다.
throttle 함수
function handle(e){
console.log(this,e);
}
// callback, closure, IIFE, call, apply
function throttle(callback,limit = 100){
let waiting = false;
return function(e){
if(!waiting){
callback.call(this,e);
waiting = true;
setTimeout(() => {
waiting = false;
}, limit);
}
}
}
ground.addEventListener('mousemove',throttle((handle),1000))
setInterval 함수로 이벤트를 제어하지 못하는 이유 -> 한번 이벤트가 호출될때마다 계속해서 쌓이기 떄문에.
우리가 원하는 것은 단 한번의 호출로 제어할 수 있도록 하는 것이다.
버블링과 캡처링
버블링
p 태그를 눌렀는데 그 바깥쪽의 모든 태그들까지 핸들러가 동작된다.
e.target : 마우스 처음 닿는 대상!
e.currentTarget: 이벤트 실행시킨 대상
ㄴ > this 로 가져올 수 있었다.
버블링 중단
e.stopPropagation
*꼭 필요한 경우를 제외하고는 버블링을 막지 않아야함!
캡쳐링 : 버블링의 역순
이벤트위임
캡쳐링과 버블링을 활용하면 강력한 이벤트 핸들링 패턴인 이벤트위임을 구현할 수 있다.
이벤트위임
공통 조상에 할당한 핸들러에서 event.target을 이용하여 실제 어디서 이벤트가 발생했는지 알 수 있다.
이를 이용해 이벤트를 핸들링한다.