[SeSACx코딩온] JS DOM 이벤트리스너
JS DOM: addEventListener
자바스크립트에서 이벤트 핸들러를 등록하는 주요 방법은 두 가지가 있습니다.
- HTML 속성(
onXXX
속성)을 사용하는 방법 - 자바스크립트의
addEventListener
메서드를 사용하는 방법
1. HTML 속성
으로 사용
<h1 onclick="clickH1()">JS 이벤트</h1>
function clickH1() {
alert('제목 클릭! 함수 이용');
}
h1
요소를 클릭할 때 clickH1
함수가 실행되어 alert이 실행됩니다.
2. addEventListener
사용
1) 버튼에 이벤트리스너 적용
<div class="btn btn--black">버튼1</div>
<div class="btn btn--green">버튼2</div>
<div class="btn btn--blue">버튼3</div>
<div class="btn btn--red">버튼4</div>
<div id="container"></div>
const btn1 = document.querySelector('.btn--black');
const btn2 = document.querySelector('.btn--green');
const btn3 = document.querySelector('.btn--blue');
const btn4 = document.querySelector('.btn--red');
const container = document.getElementById('container');
// 클릭 이벤트
btn1.addEventListener('click', function() {
alert('버튼 1을 클릭하셨네요!');
});
// mouseover 및 mouseout 이벤트
btn1.addEventListener('mouseover', function() {
btn1.style.backgroundColor = 'aqua';
});
btn1.addEventListener('mouseout', function() {
btn1.style.backgroundColor = 'rgb(44, 44, 44)';
});
// 클릭 시 새로운 요소 생성
btn2.addEventListener('click', () => {
const div = document.createElement('div');
div.style.backgroundColor = 'pink';
div.innerHTML = 'HI!!!!!';
container.append(div);
});
// 기존 요소의 색상 변경
btn3.addEventListener('click', changeColor);
function changeColor() {
const divs = document.querySelectorAll('#container div');
for (let div of divs) {
div.style.backgroundColor = 'skyblue';
}
}
// 버튼 색상 변경
btn4.addEventListener('click', changeBtnColor);
function changeBtnColor() {
this.style.backgroundColor = 'yellow';
}
참고 this. 은 함수를 실행하게 한 본 요소 자체를 일컫습니다. (예시에선 btn4.)
2) 키 이벤트
- 키 이벤트는 사용자가 키보드를 눌렀을 때 발생합니다.
- 브라우저는 발생한 이벤트에 대한 정보를 담은
이벤트 객체 (event object)
를 이벤트 리스너에 전달합니다.
const btn = document.querySelector('button');
const input = document.querySelector('input');
btn.addEventListener('click', function(event) {
console.log(event); // 이벤트 객체 출력
});
input.addEventListener('keydown', function(e) {
console.log(e);
console.log(e.code); // 눌러진 키의 고유 코드
console.log(e.key); // 입력된 값
if (e.code === 'ArrowUp') {
console.log('▲');
} else if (e.code === 'ArrowDown') {
console.log('▼');
} else {
console.log('others');
}
});
참고 mousedown 이벤트 객체는 (마우스 좌표, 버튼 번호) 정보를 가지고, keydown 이벤트 객체는 (키 코드값, 어떤 키가 눌렸는지에 대한 정보) 정보를 가집니다.
3) 폼 이벤트
<h2>Todo list</h2>
<form id="todo-form">
<input type="text" name="todo">
<button>ADD</button>
</form>
<ul class="todos"></ul>
const todoForm = document.getElementById('todo-form');
const todos = document.querySelector('.todos');
todoForm.addEventListener('submit', (e) => {
e.preventDefault(); // 폼 제출이 페이지를 새로고침하지 않도록 함 = 폼 제출을 막음, 누락 시 새로고침하면 submit되기전에 값이 사라지기에 제대로 적용되지 않음.
const todoInput = document.querySelector('input[name="todo"]');
const newTodo = todoInput.value.trim();
if (newTodo !== '') {
const newTodoLi = document.createElement('li');
newTodoLi.append(newTodo);
todos.append(newTodoLi);
}
// 입력 필드값 초기화
todoInput.value = '';
});
4) 입력 변경 및 입력 이벤트
<hr>
<h2>변경 이벤트</h2>
<input type="text" id="change-input">
<div class="intro"></div>
const chgInput = document.querySelector('#change-input');
// 변경 이벤트: 입력 필드가 포커스를 잃을 때 발생
// 입력 후 마우스 등 입력창에서 벗어나면 실행.
chgInput.addEventListener('change', function(e) {
console.log('change!!');
console.log(e.target.value);
});
// 입력 이벤트: 입력 필드의 값이 변경될 때마다 발생
// input에 키 입력 시 하단에 입력 그대로 출력.
chgInput.addEventListener('input', function() {
const div = document.querySelector('.intro');
div.textContent = this.value;
});
3. defer 에 관해
<script defer src="./index5.js"></script>
JavaScript의 defer 속성은 <script>
태그에서 사용되며, 웹페이지의 로딩이 완료된 후에 스크립트를 실행할 수 있도록 합니다.
일반적으로 <script>
태그는 HTML 파싱 중에 발견되면 즉시 다운로드되고 실행됩니다. 이는 스크립트가 다운로드되고 실행될 때까지 브라우저가 HTML 파싱을 일시 중지하게 만들어 웹페이지의 로딩 시간이 느려질 수 있습니다. 그러나 defer 속성을 사용하면 스크립트가 다운로드되긴 하지만 HTML 파싱을 차단하지 않습니다. 대신에, 스크립트는 HTML 파싱이 완료된 후에 순서대로 실행됩니다.
- DOM을 따라 반드시 순서대로 실행되어야 한다면
<script>
- DOM이나 다른 스크립트에 의존성이 없고, 실행 순서가 중요하지 않은 경우라면
<script async>
- DOM이나 다른 스크립트에 의존성이 있고, 실행 순서가 중요한 경우라면
<script defer>
스크립트의 실행 시점을 조절하는 Async와 Defer 속성
개인적으로 아무리 봐도 코드에 이상이 없는거 같은데 왜 이렇게 안되는건가
싶을 땐 거의 defer 입력으로 해결했던 경험이 있습니다. 출처에 이해 하기 쉽게 설명한 블로그가 있으니 꼭 읽어보면 좋겠습니다.
HTML 코드
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS DOM : addEventListener</title>
<script defer src="./index5.js"></script>
<style>
body {
height: 2000px;
}
.btn {
width: 80px;
height: 35px;
border-radius: 13px;
text-align: center;
line-height: 35px;
font-weight: 700;
margin: 10px;
cursor: pointer;
}
.btn--black {
background-color: rgb(44, 44, 44);
color: #fff;
}
.btn--green {
background-color: green;
color: yellow;
}
.btn--blue {
background-color: rgb(73, 73, 255);
color: bisque;
}
.btn--red {
background-color: orangered;
color: #fff;
}
</style>
</head>
<body>
<!-- <h1 onClick="alert('제목 클릭')">js 이벤트</h1> -->
<h1 onclick="clickH1()">JS 이벤트</h1>
<div class="btn btn--black">버튼1</div>
<div class="btn btn--green">버튼2</div>
<div class="btn btn--blue">버튼3</div>
<div class="btn btn--red">버튼4</div>
<div id="container"></div>
<button>Click Me</button>
<input type="text">
<h2>Todo list</h2>
<form id="todo-form">
<input type="text" name="todo">
<button>ADD</button>
</form>
<ul class="todos"></ul>
<hr>
<h2>변경 이벤트</h2>
<input type="text" id="change-input">
<div class="intro"></div>
</body>
</html>
JAVASCRIPT 코드
// js Event(이벤트)
// 어떤 사건을 의미
// ex. 버튼 클릭, 웹페이지 로드, 키가 눌렸을 때, ...
// 이벤트에 "함수" 등록 방법 2가지
// - HTML 상에서 onXXX 속성으로 등록
// - js 에서 listener 를 사용해 등록
// 1. onXXX 속성으로 등록
function clickH1() {
alert('제목 클릭! 함수 이용');
}
// 2. addEventListener
const btn1 = document.querySelector('.btn--black');
const btn2 = document.querySelector('.btn--green');
const btn3 = document.querySelector('.btn--blue');
const btn4 = document.querySelector('.btn--red');
const container = document.getElementById('container');
// addEventListener (이벤트 종류, 이벤트가 발생했을 때 일어날 일 함수로 작성)
btn1.addEventListener('click', function() {
alert('버튼 1을 클릭하셨네요!')
})
btn1.addEventListener('mouseover', function() {
btn1.style.backgroundColor = 'aqua';
})
btn1.addEventListener('mouseout', function() {
btn1.style.backgroundColor = 'rgb(44, 44, 44)';
})
btn2.addEventListener('click', () => {
const div = document.createElement('div');
div.style.backgroundColor = 'pink';
div.innerHTML = 'HI!!!!!';
container.append(div);
})
btn3.addEventListener('click', changeColor)
function changeColor() {
const divs = document.querySelectorAll('#container div')
console.log(divs);
for (let div of divs) {
div.style.backgroundColor = 'skyblue';
}
}
btn4.addEventListener('click', changeBtnColor)
function changeBtnColor() {
console.log(this); // 자기 자신 => btn4
// console.log(this.parentNode); // this를 이용해 부모 접근
this.style.backgroundColor = 'yellow';
}
// key Event
// 이벤트 객체
// - 브라우저는 발생한 이벤트에 대한 정보를 담은 "이벤트 객체 (event object)"를 이벤트 리스너에 전달.
// ex. mousedown 이벤트 발생 -> 이벤트 객체는 (마우스 좌표, 버튼 번호) 정보를 가짐.
// ex. keydown 이벤트 발생 -> 이벤트 객체는 (키 코드값, 어떤 키가 눌렸는지에 대한 정보) 정보를 가짐.
const btn = document.querySelector('button');
const input = document.querySelector('input');
btn.addEventListener('click', function(event) {
// event 객체
// 이벤트에 대한 다양한 정보를 포함.
console.log(event); // 이벤트 객체에 대한 정보 출력
})
input.addEventListener('keydown', function(e) {
console.log(e);
console.log(e.code); // 눌려진 키의 고유 코드
console.log(e.key); // input에 입력된 값
if (e.code === 'ArrowUp') {
console.log('▲');
} else if (e.code === 'ArrowDown') {
console.log('▼');
} else {
console.log('others');
}
})
// 폼 이벤트
const todoForm = document.getElementById('todo-form');
const todos = document.querySelector('.todos');
todoForm.addEventListener('submit', (e) => {
console.log('submit');
e.preventDefault(); // 폼 submit 이벤트가 새로고침 되는 걸 막음.
// 폼 제출을 막음.
const todoInput = document.querySelector('input[name="todo"]')
// console.log(todoInput.value); // 입력된 값
const newTodo = todoInput.value.trim(); // 양쪽 공백 제거
if (newTodo !== '') {
const newTodoLi = document.createElement('li'); // <li></li>
newTodoLi.append(newTodo); // <li>input 입력 값</li>
todos.append(newTodoLi);
}
// input 창 초기화
todoInput.value = '';
})
// change: input요소에 변경이 일어나고, 다른 요소를 클릭해서
// input이 포커스 아웃(blur)처리 되었을 때 일어나는 이벤트
const chgInput = document.querySelector('#change-input');
chgInput.addEventListener('change', function(e) {
console.log('change!!');
console.log(e.target.value);
})
// input에 값이 입력될 때마다 이벤트 발생
chgInput.addEventListener('input', function() {
console.log("입력 발생!");
// console.log(this.value);
const div = document.querySelector('.intro');
div.textContent = this.value;
})