이벤트
DOM 요소의 기본 동작 중단
preventDefault
메서드 이용
<!DOCTYPE html>
<html>
<body>
<a href="http://www.google.com">go</a>
<input type="checkbox">
<script>
document.querySelector('a').onclick = e => {
// a 요소의 기본 동작(지정된 링크로 이동)을 중단
e.preventDefault();
}
document.querySelector('input[type=checkbox]').onclick = e => {
// checkbox 요소의 기본 동작(체크 또는 해제)을 중단
e.preventDefault();
}
</script>
</body>
</html>
preventDefault
메서드 사용 시
<body>
<form>
<input type="checkbox" placeholder="값을 입력하세요">
</form>
<script>
document.querySelector('input[type=checkbox]').onclick = e => {
e.preventDefault();
console.log("실패");
}
</script>
</body>
이벤트 전파 방지
stopPropagation
메서드
<!DOCTYPE html>
<html>
<body>
<div class="container">
<button class="btn1">Button 1</button>
<button class="btn2">Button 2</button>
<button class="btn3">Button 3</button>
</div>
<script>
document.querySelector('.container').onclick = ({ target }) => {
if(!target.matches('.container > button')) return;
target.style.color = 'red';
}
document.querySelector('.btn2').onclick = e => {
e.stopPropagation();
e.target.style.color = 'blue';
}
</script>
</body>
</html>
- 현재 이벤트가 캡처링/버블링 단계에서 더 이상 전파되지 않도록 방지
이벤트 핸들러 어트리뷰트 방식
<!DOCTYPE html>
<html>
<body>
<button onclick="handleClick()">Click me</button>
<script>
function handleClick(button){
console.log(button); // 이벤트를 바인딩한 button 요소
console.log(this); // window
}
</script>
</body>
</html>
- 일반 함수로서 호출되는 함수 내부의
this
는 전역 객체window
를 가리킴
<!DOCTYPE html>
<html>
<body>
<button class="btn1">0</button>
<button class="btn2">0</button>
<script>
const $button1 = document.querySelector('.btn1');
const $button2 = document.querySelector('.btn2');
//이벤트 핸들러 프로퍼티 방식
$button1.onclick = function(e) {
//this는 이벤트를 바인딩한 DOM 요소를 가리킨다.
console.log(this); // $button1
console.log(e.currentTarget); // $button1
console.log(this === e.currentTarget); // true
// $button1의 textContent를 1 증가시킨다.
++this.textContent;
}
//addEventListener 메서드 방식
$button2.addEventListener('click', function(e) {
//this는 이벤트를 바인딩한 DOM 요소를 가리킨다.
console.log(this); // $button2
console.log(e.currentTarget); // $button2
console.log(this === e.currentTarget); // true
// $button2의 textContent를 1 증가시킨다.
++this.textContent;
});
</script>
</body>
</html>
- 이벤트 핸들러 프로퍼티 방식과
addEventListener
메서드 방식의this
는 이벤트를 바인딩한 DOM 요소를 가리킴(이벤트 핸들러 프로퍼티 방식과 동일)
<!DOCTYPE html>
<html>
<body>
<button class="btn1">0</button>
<button class="btn2">0</button>
<script>
const $button1 = document.querySelector('.btn1');
const $button2 = document.querySelector('.btn2');
//이벤트 핸들러 프로퍼티 방식
$button1.onclick = e => {
//this는 상위 스코프의 this를 가리킨다.
console.log(this); // window
console.log(e.currentTarget); // $button1
console.log(this === e.currentTarget); // false
// window.textContent에 NaN을 할당
++this.textContent;
};
//addEventListener 메서드 방식
$button2.addEventListener('click', e => {
//this는 상위 스코프의 this를 가리킨다.
console.log(this); // window
console.log(e.currentTarget); // $button2
console.log(this === e.currentTarget); // false
// window.textContent에 NaN을 할당
++this.textContent;
});
</script>
</body>
</html>
- 화살표 함수로 정의했을 경우
this
는 상위 스코프의this
를 가리킴 - 화살표 함수는 함수 자체의
this
바인딩을 갖지 않음
<!DOCTYPE html>
<html>
<body>
<button class="btn">0</button>
<script>
class App {
constructor() {
this.$button = document.querySelector('.btn');
this.count = 0;
// increase 메서드를 이벤트 핸들러로 등록
this.$button.onclick = this.increase;
//increase 메서드 내부의 this가 인스턴스를 가리키도록 한다.
//화살표 increase는 프로토타입 메서드가 아닌 인스턴스 메서드
this.$button.onclick = this.increase.bind(this);
}
increase() {
this.$button.textContent = ++this.count;
}
//화살표 함수
increase = () => this.$button.textContent = ++this.count;
}
</script>
</body>
</html>
- 이벤트 핸들러 내부의
this
는 이벤트를 바인딩한 DOM 요소를 가리킴 increase
메서드 내부의this
는this.$button
을 가리킴
bind()
- 새로운 함수를 생성하여 첫 인자의
value
로this
를 설정하고 이어지는 인자들은 바인드된 함수의 인수로 제공
const module = {
x: 42,
getX: function() {
return this.x;
}
};
const unboundGetX = module.getX;
console.log(unboundGetX()); // undefined
const boundGetX = unboundGetX.bind(module);
console.log(boundGetX()); // 42
이벤트 핸들러에 인수 전달
- 이벤트 핸들러 프로퍼티 방식과
addEventListener
메서드 방식은 함수 자체를 등록해야 인수 전달 가능 - 따라서, 이벤트 핸들러 내부에서 함수를 호출하거나 이벤트 핸들러 반환하는 함수를 호출하면서 인수를 전달한다.
<!DOCTYPE html>
<html>
<body>
<label>User name <input type='text'></label>
<em class="message"></em>
<script>\const MIN_USER_NAME_LENGTH = 5;
const $input = document.querySelector('input[type=text]');
const $msg= document.querySelector('.message');
const checkUserNameLength = min => {
$msg.textContent
= $input.balue.length < min ? `이름은 ${min}자 이상 입력해 주세요` : '';
}
//이벤트 핸들러 내부에서 함수를 호출하면서 인수 전달
$input.onblur = () => {
checkUserNameLength(**MIN_USER_NAME_LENGTH**);
};
//이벤트 핸들러를 반환하는 함수
const checkUserNameLength = min => e => {
$msg.textContent
= $input.balue.length < min ? `이름은 ${min}자 이상 입력해 주세요` : '';
};
//이벤트 핸들러를 반환하는 함수를 호출하면서 인수 전달
$input.onblur = checkUserNameLength(**MIN_USER_NAME_LENGTH**);
</script>
</body>
</html>
- 인수
MIN_USER_NAME_LENGTH
커스텀 이벤트 생성
커스텀 이벤트: 개발자가 임의의 이벤트 타입을 지정한 이벤트
Event의 생성자
- 이벤트 클래스 계층의 제일 꼭대기엔
Event
클래스가 있음
//Event 객체 생성
let event = new Event(type[, options]);
type
- 이벤트 타입을 나타내는 문자열
options
- 두 개의 선택 프로퍼티가 있는 객체
bubbles: true/false
⇒ 버블링cancelable: true/false
⇒ 기본 동작 실행 방지
//KeyboardEvent 생성자 함수로 keyup 이벤트 타입의 커스텀 이벤트 객체를 생성
const keyboardEvent = new KeyboardEvent('keyup');
console.log(keyboardEvent.type); // keyup
//CustomEvent 생성자 함수로 foo 이벤트 타입의 커스텀 이벤트 객체를 생성
const customEvent= new KeyboardEvent('foo');
console.log(customEvent.type); // foo
//MouseEvent 생성자 함수로 click 이벤트 타입의 커스텀 이벤트 객체 생성
const customEvent = new MouseEvent('click');
console.log(customEvent.type); // click
console.log(customEvent.bubbles); // false
console.log(customEvent.cancelable); // false
- 생성된 커스텀 이벤트 객체는 버블링되지 않으며
preventDefault
메서드로 취소할 수 없다. (false
로 기본 설정)
true로 설정하기 위해서는?
⇒ 이벤트 생성자 함수의 두 번째 인수로 bubbles
또는 cancelable
프로퍼티를 갖는 객체 전달
- 반드시 명시적으로 설정해야함
const customEvent = new MouseEvent('click', {
bubbles: true,
cancelable: true
});
console.log(customEvent.bubbles); // true
console.log(customEvent.cancelable); // true
이외의 프로퍼티
- 커스텀 이벤트 객체에는 이벤트 타입에 따라 가지는 이벤트 고유의 프로퍼티 값 지정 가능
⇒ 마찬가지로 이벤트 생성자 함수의 두 번째 인수로 프로퍼티 전달
// MouseEvent 생성자 함수로 click 이벤트 타입의 커스텀 이벤트 객체 생성
const mouseEvent = new MouseEvent('click', {
bubbles: true,
cancelable: true,
clientX: 50,
clientY: 100
});
console.log(mouseEvent.clientX); // 50
console.log(mouseEvent.clientY); // 100
// KeyboardEvent 생성자 함수로 keyup 이벤트 타입의 커스텀 이벤트 객체 생성
const keyboardEvent = new KeyboardEvent('keyup', {key: 'Enter'});
console.log(keyboardEvent.key); // Enter
isTrusted
프로퍼티
boolean
값 반환- 사용자 액션에 의해 생성된 이벤트는
true
EventTarget.dispatchEvent()
로 발송한 이벤트나 스크립트를 통해 생성되었다면false
- 사용자 액션에 의해 생성된 이벤트는
const customEvent = new InputEvent('foo');
console.log(customEvent.isTrusted); // false
커스텀 이벤트 디스패치
- 생성된 커스텀 이벤트를
dispatchEvent
메서드로 디스패치(이벤트를 발생시키는 행위)를 해야 한다.
<!DOCTYPE html>
<html>
<body>
<button class="btn">0</button>
<script>
const $button = document.querySelector('.btn');
// 버튼 요소에 foo 커스텀 이벤트 핸들러를 등록
$button.addEventListener('click', e => {
console.log(e);
alert(`${e} Clicked!`);
});
// 커스텀 이벤트 생성
const customEvent = new MouseEvent('click');
// 커스텀 이벤트 디스패치(동기 처리). click 이벤트 발생
$button.dispatchEvent(customEvent);
</script>
</body>
</html>
다양한 이벤트
UIEvent
FocusEvent
MouseEvent
WheelEvent
KeyboardEvent
- 등등의 이벤트는
new Event
를 통한 event 객체를 생성할 수 없고, 반드시 관련 내장 클래스를 사용해야 한다.
let event = new MouseEvent("click", {
bubbles: true,
cancelable: true,
clientX: 100,
clientY: 100
});
console.log(event.clientX); // 100
//Event 생성자를 사용한 표준 프로퍼티
let event = new Event("click", {
bubbles: true, // Event 생성자에선
cancelable: true, // bubbles와 cancelable 프로퍼티만 동작합니다.
clientX: 100,
clientY: 100
});
console.log(event.clientX); // undefined
CustomEvent 이용한 커스텀 이벤트
CustomEvent
vsEvent
CustomEvent
⇒ 두 번째 인수에 객체가 들어갈 수 있는데detail
프로퍼티를 추가해 커스텀 이벤트 관련 정보를 명시하여 이벤트에 전달detail
프로퍼티 사용 이유: 다른 이벤트 프로퍼티와의 충돌을 피하기 위함<h1 id="elem">Hi! javascript</h1> <script> elem.addEventListener("hello", function(event) { console.log(event.detail.name); // javascript }); elem.dispatchEvent(new CustomEvent("hello", { detail: { name: "javascript" } })); </script>
'Frontend > JavaScript' 카테고리의 다른 글
[JavaScript] javascript 주요 개념 간단 정리 (0) | 2023.02.22 |
---|---|
[JavaScript] 제너레이터와 async/await (0) | 2023.02.16 |
[JavaScript] Set (2) | 2023.02.16 |
[JavaScript] 이터러블 (1) | 2023.02.16 |
[JavaScript] 함수와 일급 객체 (0) | 2022.11.08 |