[JS][Udemy] DOM event +
► Events
- 코드를 이용해 동작하는 행동 → 스크롤, 마우스 동작 시 새로운 요소 생성 등
► Inline Event
- html안에 인라인을 넣는 방법 → 권장하지 않음!
<body>
<section onclick="alert('section clicked')">
<p onclick="alert('paragraph clicked')">
I am a paragraph:
<button onclick="alert('button clicked')">Click</button>
</p>
</section>
</body>
⎣'click' 버튼을 눌렀을 때 'button clicked' 경고창이 나타나고 확인을 누르면 'paragragh clicked' → 'section clicked' 경고창이 이어서 나타남
► addEventListener
- addEventListener는 원하는 만큼 콜백 함수를 사용할 수 있다
- onclick은 마지막에 선언된 것만 출력됨
- https://developer.mozilla.org/ko/docs/Web/API/EventTarget/addEventListener
// index.html
<div id="container">
Click To Hide
<button id="changeColor">Change Color</button>
</div>
// app.js
const button = document.querySelector('#changeColor'); // button id 선택
const container = document.querySelector('#container'); // div id 선택
button.addEventListener('click', function (e) { // button이 클릭되었을 때 다음 함수 실행
container.style.backgroundColor = makeRandColor(); // div의 색상을 랜덤으로 변경
e.stopPropagation(); // 위의 이벤트가 전달되는 것을 막음
})
// div가 클릭되었을 때 숨기기
container.addEventListener('click', function () {
container.classList.toggle('hide');
})
// 랜덤 컬러 함수 : rgb 색상을 랜덤으로 생성해서 반환
const makeRandColor = () => {
const r = Math.floor(Math.random() * 255);
const g = Math.floor(Math.random() * 255);
const b = Math.floor(Math.random() * 255);
return `rgb(${r}, ${g}, ${b})`;
}
⎣ 왜 인라인 이벤트인 onclick을 사용하지않고 addEventListener를 통해 click을 사용할까?
→ onclick은 동일한 이벤트에 대해 두 개의 서로 다른 콜백 함수를 저장할 수 없기 때문에
다시말해,
button.onclick = console.log('hello')
button.onclick = console.log('hi')
위처럼 차례대로 선언되었다면 마지막에 선언한것만 실행이 됨
하지만, addEventListener는 원하는 만큼 콜백 함수를 사용할 수 있다
⎣ 'change color' 버튼 누를때 마다 색상 변경됨
⎣ 버튼이외의 공간을 클릭할 경우 div로 설정된 부분이 전부 사라짐
// index.html
<body>
<h1>Welcome!</h1>
<button id="changeColor">Click Me</button>
</body>
// app.js
const btn = document.querySelector('button') // button 선택
const h1 = document.querySelector('h1') // h1 선택
btn.addEventListener('click', function (){ // button을 클릭했을 때 함수 실행
const newColor = makeRandColor() // 랜덤컬러 변수 정의
document.body.style.backgroundColor = newColor // body의 색상이 랜덤으로 변경
h1.innerText = newColor // h1 텍스트가 newColor 변수로 바뀌는데
// 아래에서 newColor의 변수는 rgb컬러 번호로 저장해둠
})
const makeRandColor = () => { // 랜덤컬러 함수
const r = Math.floor(Math.random() * 255)
const g = Math.floor(Math.random() * 255)
const b = Math.floor(Math.random() * 255)
return newColor = `rgb(${r}, ${g}, ${b})` // rgb 컬러를 위에서 정해둔 newColor변수에 저장
}
⎣ 'Click Me' 버튼 누를때 마다 배경색상과 rgb 색상번호가 바뀜
► Event & 'this' keyword
<style>
button {
width: 100px;
height: 100px;
margin: 20px;
}
</style>
</head>
<body>
<button>CLICK</button>
<button>CLICK</button>
<button>CLICK</button>
<h1>Click Me!</h1>
<h1>Click Me!</h1>
<h1>Click Me!</h1>
// 랜덤 컬러 함수 생성
const makeRandColor = () => {
const r = Math.floor(Math.random() * 255);
const g = Math.floor(Math.random() * 255);
const b = Math.floor(Math.random() * 255);
return `rgb(${r}, ${g}, ${b})`;
}
// 버튼 태그 선택
const buttons = document.querySelectorAll('button');
// 버튼 태그 'click' 클릭 시 colorize 함수 실행
// colorize 함수는 배경색상 / 색상 랜덤으로 변경
for (let button of buttons) {
button.addEventListener('click', colorize)
}
// h1 태그 선택 후 반복문으로 h1태그('click me') 선택 시
// 위와 같이 색상 변경
const h1s = document.querySelectorAll('h1');
for (let h1 of h1s) {
h1.addEventListener('click', colorize)
// h1을 this키워드로 바꿔서 사용해도 괜찮지만 중복된다는 사실을 변함이 없기 때문에
// 랜덤 컬러부분을 따로 함수로 만들어주는게 보기 편하다
}
// colorize 함수
function colorize() {
this.style.backgroundColor = makeRandColor(); // h1, button 제너릭 함수라서 엑세스 불가능
this.style.color = makeRandColor(); // 따라서 this 키워드 사용
}
// this 키워드를 사용하지 않았을 경우
// 중복이 많이 발생
for (let button of buttons) {
button.addEventListener('click', function() {
button.style.backgroundColor = makeRandColor();
button.style.color = makeRandColor();
})
}
const h1s = document.querySelectorAll('h1');
for (let h1 of h1s) {
h1.addEventListener('click', function() {
h1.style.backgroundColor = makeRandColor();
h1.style.color = makeRandColor();
})
}
► Event object
⎣ 이벤트에 대한 정보를 담고 있는 객체
// input 태그 선택
const input = document.querySelector('input');
input.addEventListener('keydown', function (e) {
console.log(e.key) // key : 사용자가 누르는 키 : 사용자가 변경할 수 있음
console.log(e.code) // code : 키보드에서의 실제 위치 : 기본 값
})
⎣ 한글 'ㅁ'을 입력하면 key A : 키보드 위치 출력
⎣ 영어 ' a' 를 입력하면 key A : 키보드 위치 출력
► Keyboard Event
<body>
<button>CLICK</button>
<input type="text">
<script src="app.js"></script>
</body>
// button 태그 선택 후 click할때 evt 함수실행
document.querySelector('button').addEventListener('click', function (evt) {
console.log(evt)
})
// window 전체에 대한 이벤트 리스너 추가
// 키다운, 키업을 사용하려면 window.addEventListener
window.addEventListener('keydown', function (e) {
switch (e.code) { // code는 키보드 위치
case 'ArrowUp': // 위 방향키
console.log("UP!");
break;
case 'ArrowDown': // 아래 방향키
console.log("DOWN!");
break;
case 'ArrowLeft': // 왼쪽 방향키
console.log("LEFT!");
break;
case 'ArrowRight': // 오른쪽 방향키
console.log("RIGHT!");
break
default: // 방향키 이외의 것들
console.log("IGNORED!")
}
})
⎣ 방향키 이외의 다른 것을 입력하면 'IGNORED!'
⎣ break 하지않으면 계속 출력됨 [switch 조건문] : 2023.03.13 - [JS] - [JS][udemy] JS 판단 내리기
► Form Events & PreventDefault
// index.html
<body>
<h1>Form Events</h1>
<form action="/dogs" id="tweetForm">
<input type="text" name="username" placeholder="username">
<input type="text" name="tweet" placeholder="tweet">
<button>Post Tweet</button>
</form>
<h2>Tweets:</h2>
<ul id="tweets">
</ul>
// app.js
const tweetForm = document.querySelector('#tweetForm');
const tweetsContainer = document.querySelector('#tweets');
tweetForm.addEventListener('submit', function (e) {
e.preventDefault(); // action에 전송되는 것을 막음
// const usernameInput = document.querySelectorAll('input')[0];
// const tweetInput = document.querySelectorAll('input')[1];
// 주석처리 된 부분과 결과는 같음 -> 다만 순서가 바뀌면 값도 바뀜
// 방식이 다른 것인데 각 태그에 name을 부여함 -> 순서가 바껴도 괜찮음
const usernameInput = tweetForm.elements.username;
const tweetInput = tweetForm.elements.tweet;
// value는 입력된 값을 페이지에 출력
addTweet(usernameInput.value, tweetInput.value)
// 입력값을 초기화
usernameInput.value = '';
tweetInput.value = '';
});
const addTweet = (username, tweet) => {
// 새로운 태그 생성 li, b
const newTweet = document.createElement('li');
const bTag = document.createElement('b');
// 자식요소로 넣어주기
bTag.append(username) // bold 태그 안에 username (input태그)
newTweet.append(bTag); // bold 태그 안에 li태그
newTweet.append(`- ${tweet}`) // li 태그 사이에 들어가는 글자 ' - 8670303'
tweetsContainer.append(newTweet); // ul태그 안에 li태그
}
// <li><b>winter_k</b> - 8670303</li>
⎣ 입력하고 post tweet 클릭하면 tweets아래에 추가됨
⎣ console.log(newTweet) 하면 위의 결과가 나타남 : bold 태그 안에 li 태그
► ChangeAndInputEvents
<!DOCTYPE html>
<head>
<title>Input Event</title>
<!--LEAVE THESE LINES ALONE, PLEASE! THEY MAKE THE LIVE PREVIEW WORK!-->
<script src="node_modules/babel-polyfill/dist/polyfill.js" type="text/javascript"> </script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<h1>Enter Your Username</h1>
<input type="text" id="username">
</body>
</html>
const h1 = document.querySelector('h1')
const usernameInput = document.querySelector('#username')
usernameInput.addEventListener('input', function (e) {
const username = usernameInput.value
h1.innerText = `Welcome, ${username}`
if (username.length === 0) { // 아무것도 입력하지 않았을 때
h1.innerText = 'Enter Your Username'
}
})
► 이벤트 핸들링 / 버블링 / 캡처링 / 차단
- 핸들링 : 사용자가 행하는 모든 동작
- 바인딩 : 이벤트 핸들링을 하기 위해 이벤트를 받을 화면 요소를 선택하고 그 요소와 이벤트를 연결해주는 것
- 버블링 : 하위요소에서 상위요소로의 이벤트 전파 방식
- 다시말해, 자식요소에 발생한 이벤트가 상위의 부모요소에까지 영향을 미치는 것
- 캡처링 : 상위요소에서 하위요소로의 이벤트 전파 방식
- 차단 : 이벤트 버블링은 window까지 전달되는데 이를 막기위해서는 stopPropagation()메소드를 사용해 이벤트 전파 차단하면 됨
- 이벤트 캡처링의 경우에 차단 메소드를 사용하면 최상위 요소의 이벤트만 동작시키고 하위 요소들로 이벤트를 전달하지 않음
https://developer.mozilla.org/ko/docs/Learn/JavaScript/Building_blocks/Events
이벤트 입문 - Web 개발 학습하기 | MDN
이벤트(event)란 여러분이 프로그래밍하고 있는 시스템에서 일어나는 사건(action) 혹은 발생(occurrence)인데, 이는 여러분이 원한다면 그것들에 어떠한 방식으로 응답할 수 있도록 시스템이 말해주
developer.mozilla.org