🦁멋쟁이사자처럼 백엔드 부트캠프 13기 🦁
TIL 회고 - [27]일차
🚀27일차에는 자바스크립트의 이벤트 처리에 대해 배울 수 있었다.
HTML과 연동되어 동작하면서 자바스크립트 코드로 HTML태그에 이벤트를 생성하는 방법을 보니
웹 애플리케이션이나 웹페이지에서 자주 보이는 동작과 유사하였다.
회고를 진행하면서 이벤트를 응용하는 실습을 해봐야겠다고 생각했다.
자바스크립트 이벤트
- 이벤트를 처리할때 HTML태그에 이벤트를 적용해주게 되는데
HTML태그와 자바스크립트가 연동되는 과정이라고 볼 수 있다. - HTML의 DOM에 자바스크립트의 이벤트를 적용해주는 과정을 하게 된다.
DOM
- 문서 객체 모델 (Document Object Model)
- XML이나 HTML문서에 접근하기 위한 일종의 “인터페이스”
- 이 문서 객체 모델 (DOM)은 문서 내의 모든 요소를 정의하고, 각각 요소에 접근하는 방법을 제공
- 만약 사용자의 입력(혹은 상호작용)에 따라 동적으로 브라우저의 UI를 업데이트하고 싶다면
자바스크립트를 연동해주어야한다. - 보통 상호작용이 많은 경우 Vanilla JavaScript를 사용해서는 많은 양의 코드로 관리가 어려워지므로
➡️React, Vue, Angular 등의 도구를 사용한다. - Vanilla JavaScript : 순정 자바스크립트만 사용 = 라이브러리/프레임워크는 사용하지 않음
카운터
- 버튼을 클릭하면 숫자가 올라가거나 내려가는 기능 구현
<body>
<!--이벤트 처리-->
<!--이벤트 처리할 대상 (어느 태그에 사용할 것)-->
<script>
// 이벤트 대상 = addEventListener() : 이벤트를 걸어주는 표준함수
</script>
</body>
- 기본적인 구조 : 이벤트를 걸어주는 표준함수 addEventListener()를 사용
- addEventListener()의 인자 :
💡addEventListener(eventName, eventHandler, ToCapture);
➡️eventName : type이라고도 불리며, 클릭이나 드래그 등 수신할 이벤트 타입을 나타냄
➡️eventHandler : Listener라고도 불리며 실제 이벤트가 발생되었을때 할 일을 지정한다
즉 Event 인터페이스를 구현한 객체 (=지정한 이벤트)를 수신할 객체이며, “함수로 전달”한다.
(ex. 버튼을 클릭했을때 구현할 작업을 “함수로 전달”)
➡️ToCapture : options라고도 불리며, 기본값은 false이지만 생략가능.
이벤트가 전달되기 전에 이 것이 먼저 발동되어야한다고 알리는 불리언(boolean)값
HTML 태그 찾기
<button>클릭</button>
<script>
// 이벤트 대상 = addEventListener() : 이벤트를 걸어주는 표준함수
const btn = document.querySelector("button");
</script>
- querySelector()로 “button”태그를 단순히 넘겨주기만 하면 버튼을 찾아낼 수 있다.
<button>클릭</button>
<script>
// 이벤트 대상 = addEventListener() : 이벤트를 걸어주는 표준함수
const btn = document.querySelector("button");
// 버튼의 EventHandler (두번째 인자) 정의
const clicked = () => {
alert("버튼이 클릭되었습니다.");
};
btn.addEventListener("click", clicked);
</script>
- 첫번째 인자로 이벤트 타입을 정의하고
- 두번째 인자로 함수를 전달한다. (함수는 밖에서 정의한 clicked()를 사용한다.)
- 여기서 버튼이 한 개 더 들어오게되면 이때부터는 버튼을 구분하기 위해서 버튼 태그의 id를 지정해주어야한다.
- 이 경우 querySelector()의 형태또한 바뀌게된다. ➡️document.querySelector("#btn2");
- id값이므로 “#btn2”로 찾는다. 만약 class값이면 (".btn2")일 것이다.
▶️실습 - “날짜 출력” 버튼
// 버튼2는 현재 날짜를 팝업으로 출력하도록 이벤트 구현
const btn2 = document.querySelector("#btn2");
btn2.addEventListener("click", () => {
const date = new Date();
const formattedDate = date.toLocaleDateString("ko-KR", {
year:"numeric",
month:"2-digit",
day:"2-digit",
});
alert(formattedDate);
});
- new로 Date()함수를 생성한다음 toLocalDateString()으로 출력 포맷 형식을 지정해주어야한다.
- 포맷을 지정하지 않으면 1970년 첫 날을 기준으로 현재까지의 지내온 시간을 ms(밀리초)로 반환하기 때문에
긴 숫자만 출력된다. (=타임스탬프) - year 속성 : numeric ("2025"를 표시), 2-digit ("25"를 표시)
- month 속성 : numeric ("1"을 표시), 2-digit ("01"를 의미), long ("1월"로 표시)
- day, hour, minute, second 속성들도 numeric, 2-digit 속성값을 가짐
🚀실습 - 레벨업 버튼 구현
// 버튼 3 - 숫자를 올리도록 이벤트 구현
const btn3 = document.querySelector("#btn3");
let count = 0;
btn3.addEventListener("click", () => {
count++;
let printCount = "[+1 레벨업!] Lv." + count;
alert(printCount);
});
querySelectorAll()
- querySelector() : 단일 태그만 찾아낸다. 따라서 버튼이 3개가 있으면 첫번째 만난 버튼의 요소만 리턴하게된다.
- querySelectorAll() : 모든 요소를 찾아서 리스트로 리턴한다.
ex. querySelectorAll(”button”) ➡️ 모든 버튼을 찾아서 리스트로 리턴한다.
getElementById()
- Id값과 일치하는 태그를 찾아 리턴 (단일)
<button class="btn">class 버튼1</button>
<button class="btn">class 버튼2</button>
<button class="btn">class 버튼3</button>
<button id="button">id를 가진 버튼</button>
const btn_id = document.getElementById("button"); // Element 여서 하나만 리턴
console.log("\\n-----[버튼 id 찾기]-----");
console.log(btn_id);
getElementsByTagName()
- 태그이름과 일치하는 태그들을 찾아 배열로 리턴
<body>
<!-- 버튼들...-->
<script>
const btns = document.getElementsByTagName("button"); // Elements 여서 배열로 리턴
console.log("\\n-----[버튼들의 태그 이름 찾기]-----");
console.log(btns);
</script>
</body>
getElementsByClassName()
- 클래스 이름과 일치하는 태그들을 찾아 배열로 리턴
<body>
<!-- 버튼들...-->
<script>
function testCode() {
alert("테스트 함수입니다.");
}
const btn_classes = document.getElementsByClassName("btn"); // 클래스 이름이 btn인 Elements 배열로 리턴
console.log("\\n-----[버튼들의 클래스 이름 찾기]-----");
console.log(btn_classes);
btn_classes[0].addEventListener("click", testCode);
</script>
</body>
- btn_classes[0].addEventListener(”click”, testCode”);
➡️배열이기때문에 인덱스로 접근하여 하나의 태그를 선택하여 이벤트를 설정해주어야한다.
- 브라우저를 출력해보면 이처럼 배열로 받아온 것을 확인할 수 있다.
▶️실습 - 배경색상을 변경해주는 버튼 구현
<body>
<button>배경색상 변경</button>
<script>
function changeColor() {
const color = prompt();
document.body.style.backgroundColor = color;
}
const btn = document.querySelector("button");
btn.addEventListener("click", changeColor);
</script>
</body>
- document.body.style.backgroundColor
➡️document 문서의 body 태그에 들어가서 그 body태그의 style 속성 중 backgroundColor를 설정 - prompt()
➡️입력을 받는데 red, blue, lightgreen 처럼 색상의 "이름"값을 받아서 바로 backgroundColor에 적용
▶️실습 - 입력받은 텍스트를 화면에 출력
- <div> 부분에 입력받은 텍스트를 출력
<body>
<button id="input_btn">화면에 텍스트 입력</button>
<div></div>
<script>
const btn2 = document.querySelector("#input_btn");
btn2.addEventListener("click", () => {
const text = prompt();
document.querySelector("div").innerHTML = text;
});
</script>
</body>
- prompt()로 사용자 입력을 받고 querySelector(”div”)로 div태그를 찾아서 innerHTML을 통해 텍스트를 바꾼다.
- 여러 개의 div가 있어도 “첫번째 만난 요소만”을 변경하기때문에 사용이 가능한 방법
➡️만약 여러개의 div를 한번에 바꾸고 싶다면 클래스로 지정하고,
특정 div만 바꾸고 싶다면 id값을 지정하면 될 것이다.
🚀실습 - 여러 개의 div 태그를 입력된 값으로 바꾸기
- 만약 여러개의 div이지만 아무속성이 없는 div태그, 클래스를 가진 div태그, id를 가진 div태그는
어떻게 선택해서 prompt()로 바꿔주어야할까를 고민해보았다.
<body>
<div></div>
<div class="messages"></div>
<div class="messages"></div>
<div class="messages"></div>
<div id="id_msg"></div>
<script>
// 텍스트 입력 버튼을 눌렀을 경우
const btn2 = document.querySelector("#input_btn");
btn2.addEventListener("click", () => {
const text = prompt();
document.querySelector("div").innerHTML = text;
const texts = document.querySelectorAll(".messages");
for (let i = 0; i < texts.length; i++) {
texts[i].innerHTML = text;
}
document.querySelector("#id_msg").innerHTML = text;
});
</script>
</body>
- <div> : 아무속성이 없는 이 태그는
➡️querySelector(”div”).innerHTML = text; 로 접근 - <div class=”messages”> : 클래스가 있는 태그들은
➡️querySelectorAll(”.div”)로 해당 클래스가 있는 태그들이 texts 에 담기게되고
➡️for문 안에서 각 데이터들을 index로 탐색하여 innerHTML로 인해 text가 바뀌게된다. - <div id=”id_msg”> : id가 있는 태그는
➡️querySelector(”#id_msg”).innerHTML = text; 로 접근
- Element를 확인해보면 모두 텍스트가 바뀌어서 잘 출력됨을 확인할 수 있다.
▶️실습 - 화면 클릭 시 배경색 변경
- Math.floor(Math.random() * 256) 사용 : 랜덤한 r, g, b값을 계속 갱신
- 클릭 이벤트가 발생할때마다 함수에서 r, g, b 값을 랜덤으로 변경
<body>
<div>
<h2>화면을 클릭하면<br />배경색을 변경합니다.</h2>
</div>
<script>
function changeColor() {
// Math.floor(Math.random()*256) 활용
let r = Math.floor(Math.random() * 256);
let g = Math.floor(Math.random() * 256);
let b = Math.floor(Math.random() * 256);
document.body.style.backgroundColor = `rgb(${r}, ${g}, ${b})`;
}
document.addEventListener("click", changeColor);
</script>
</body>
- backgroundColor로 색을 바꿀때는 템플릿 리터럴을 활용해 실제 값을 바로 넣어줄 수 있도록 한다.
▶️실습 - 화면 클릭 시 배경색 변경 (함수 분리)
<script>
function changeColor() {
document.body.style.backgroundColor = makeColor();
console.log(makeColor());
}
function makeColor() {
let r = Math.floor(Math.random() * 256);
let g = Math.floor(Math.random() * 256);
let b = Math.floor(Math.random() * 256);
return `rgb(${r}, ${g}, ${b})`;
}
document.addEventListener("click", changeColor);
</script>
- 함수를 분리하여 리턴값으로 받아서 갱신할 수 있도록 구현할 수도 있다.
- changeColor된 부분에서 console.log()로 출력해보면 rgb값이 잘 출력되는 것도 확인할 수 있다.
이벤트 삭제
// 이벤트 삭제
document.removeEventListener("click", changeColor);
- 위에서 정의되었던 이벤트가 한번 수행된 후에 이벤트가 삭제되어
화면을 클릭하여도 더 이상 배경색상이 바뀌지 않는다.
// 3초 후 이벤트 삭제
setTimeout(() => {
document.removeEventListener("click", changeColor);
console.log("이벤트가 삭제되었습니다.")
}, 3000)
- 지연시간 후에 이벤트를 삭제하도록 setTimeout()함수를 사용할 수도 있다.
이벤트 버블링
- Event Bubbling
- 이벤트 안쪽에서 바깥쪽으로 전파되는 방식을 거품이 일어나는듯 하여 “이벤트 버블링”
- 물(이벤트)가 아래에서 위로 올라오는 거품인 상황 ➡️ 하위요소에서 상위요소로 전파
<style>
* {
border: 3px solid black;
}
</style>
<!-- ... -->
<body>
<div onclick="alert('outer-div');">
<div onclick="alert('inner-div');">
<div onclick="alert('inner-inner_div');">
<h1 onclick="alert('h1');">
<p onclick="alert('p');">p태그</p>
</h1>
</div>
</div>
</div>
</body>
- 이벤트버블링 : 위에 있는 <p>태그를 누르면 박스들이 겹쳐져있기때문에
다른 박스들도 함께 눌리게되는 전파 방식을 가진다.
이벤트 캡처링
- Event Capturing
- 이벤트 바깥쪽에서 안쪽으로 전파되는 방식을 “이벤트 캡처링” (추가된 방식)
- 비(이벤트)가 내리듯 위에서 아래로 내리는 상황 ➡️ 상위 요소에서 하위 요소로 전파
- e.stopPropagation(); ➡️ 이벤트 전파를 막아주는 역할을 하는 함수
<body>
<div class="pink">
<div class="red"></div>
</div>
<script>
let pinkbox = document.querySelector(".pink");
let redbox = document.querySelector(".red");
let body = document.querySelector("body");
let html = document.querySelector("html");
pinkbox.addEventListener(
"click",
function (e) {
// e.stopPropagation();
alert("pink box!!");
},
false
);
// ...다른 박스들 또한 addEventListener 추가...
</script>
</body>
- 이벤트 전파를 막아주는 함수인 e.stopPropagation() 을 주석처리하여 테스트해보면
핑크박스가 눌렸을때 바깥쪽에서 안쪽으로 이벤트가 전파되는 “이벤트 캡처링”방식을 가진다. - 즉 각 이벤트 리스너에서 ToCapture (세번째 인자 옵션)을 기본값 false로 두면
➡️안에서 밖으로 이벤트가 전파되는 "이벤트 버블링" 방식
➡️클릭 이벤트가 발생했을 때: .red → .pink → body → html 순서로 전달 - ToCapture(세번쨰 인자 옵션)을 true로 바꿔주면
➡️밖에서 안으로 이벤트가 전파되는 "이벤트 캡처링" 방식
➡️클릭 이벤트가 발생했을 때: html → body → .pink → .red 순서로 전달 - e.stopPropagation을 특정태그에서 걸어주면 그 태그의 시점에서 이벤트 전파가 멈춘다.
- 이벤트 캡처링의 예시이다. 핑크박스 → body box → html box로 이벤트가 전파되고 있다.
🚀실습 - 행복지수와 불쾌지수
<body>
<button id="button-a">행복지수 증가</button>
<button id="button-b">불쾌지수 감소</button>
<h1>행복지수 : [ <span id="counter-a">0</span> ]%</h1>
<h1>불쾌지수 : [ <span id="counter-b">0</span> ]%</h1>
<script>
let count1 = 0;
let count2 = 0;
function increaseCounter() {
count1++;
document.body.querySelector("#counter-a").innerHTML = count1.toString();
}
function decreaseCounter() {
count2--;
document.body.querySelector("#counter-b").innerHTML = count2.toString();
}
const btn = document.querySelector("#button-a");
btn.addEventListener("click", increaseCounter);
const btn2 = document.querySelector("#button-b");
btn2.addEventListener("click", decreaseCounter);
</script>
</body>
- 각각 increaseCounter()와 decreaseCounter() 함수로 구현하고
- querySelector를 통해 <span>태그들을 찾은 후 innerHTML로 값을 변경해준다.
- 값을 변경할때는 count1, count2값이 정수이기때문에 toString()함수를 통해 문자열로 바꿔주어도되고,
그대로 숫자로 출력하고싶으면 count1, count2만 출력해주어도 된다. - 실행과정
➡️ “행복지수 증가” 버튼 선택(#button-a) 후 클릭 → btn 이벤트 발생 → increaseCounter 이벤트 핸들러 실행
→ count값 증가 후 span 태그 문자 수정
➡️ “불쾌지수 증가” 버튼 선택(#button-b) 후 클릭 → btn 이벤트 발생 → decreaseCounter 이벤트 핸들러 실행
→ count값 감소 후 span 태그 문자 수정
이벤트가 발생한 객체 가져오기 (target)
- 함수를 호출할때 이벤트가 발생했던 객체를 첫번째 인자로 넣어서 보내준다.
➡️(const increaseFunc = (event) => …) : 주로 event, e 이름으로 쓰인다.
➡️(const increaseFunc = () => …) : 이렇게 받지 않을 수도 있다.
<script>
const increaseFunc = (e) => {
console.log(e.target.id)
}
</script>
- e (event 발생할때 발생하는 객체) 를 통해 화살표함수를 만든다.
<script>
const increaseFunc = function(e){
console.log(this.id);
}
</script>
- 일반함수로 정의되었을 경우에는 this키워드로 이 객체(Object)에 접근할 수 있을 것이지만
화살표함수로 정의되었을 경우의 this는 Window객체를 가리키기때문에 - 화살표함수에서의 this 사용은 적합하지 않은 방법이다.
if(e.target.id == "button-a"){
counterA.innerHTML = Number(counterA.innerHTML) + 1;
else {
counterB.innerHTML = Number(counterB.innerHTML) + 1;
- event발생 객체를 가져와서 id값을 탐색하고 ‘button-a’인 버튼의 경우에는
- counterA span태그의 innerHTML의 문자를 바꿔주는데
➡️Number()를 이용하여 +1을 해주는 방법
➡️toString() : (정수 → 문자열) 형변환 방법
➡️parseInt() : (문자열 → 정수) 형변환 방법 등을 다양하게 사용해볼 수 있다.
🚀실습 - 강우 확률 프로그램
- 클릭 이벤트 발생 시 어떤 버튼이 클릭되었는지 알기 위해 event.target 활용
➡️counter(event) 함수에서 클릭 이벤트가 발생한 버튼을 event.target으로 식별
➡️클릭된 버튼의 id 값을 기준으로 조건 분기. ex. event.target.id
<body>
<h1>비 올 확률 : [ <span id="rainfall">0</span> ]%</h1>
<button id="button-a">비 올 확률 증가</button>
<button id="button-b">비 올 확률 감소</button>
<script>
let count = 0;
function counter(event) {
const clickedButtonId = event.target.id; // 클릭된 버튼 ID 확인 가능
if (clickedButtonId === "button-a") {
count++;
} else if (clickedButtonId === "button-b") {
count--;
}
document.body.querySelector("#rainfall").innerHTML = count.toString();
}
const btn = document.querySelector("#button-a");
btn.addEventListener("click", counter);
const btn2 = document.querySelector("#button-b");
btn2.addEventListener("click", counter);
</script>
</body>
- <span>태그를 두 개로 나눠서 행복지수, 불쾌지수를 출력했던 부분을 수정하여
- 결과를 가져와 출력할 <span>태그를 하나로 만들었다.
- 버튼 별로 다른 기능을 구현하여 이 <span>태그의 텍스트 값을 바꾸는 실습을 해볼 수 있었다.
form태그
▶️실습 - 회원가입 폼 만들기
- <input> 태그의 속성 중 value=”기본값” 설정
➡️input 폼 안에 “기본값”이 미리 작성되어있는 상태로 확인 가능
➡️이를 활용하여 input요소.value 로 input태그에 입력된 값이 무엇인지 찾아낼 수 있다. - 요구사항 :
➡️이름이 입력되지 않았다면 “이름을 입력하세요” 메시지 출력
➡️비밀번호가 입력되지 않았거나 (비밀번호와 비밀번호확인)의 입력값이 다르다면
"알맞은 비밀번호를 입력하세요" 출력 - 이벤트는 submit의 이벤트이름으로 들어올 것이다 (속성 eventName 부분에 속성 "submit" 을 인자로 전달)
<form action="08.html" id="myForm">
<label for="name">이름</label>
<input type="text" name="name" id="name" /><br />
<label for="password">비밀번호</label>
<input type="password" name="password" id="password" /><br />
<label for="checkPassword">비밀번호 확인</label>
<input type="password" name="checkPassword" id="checkPassword" /><br />
<input type="submit" value="등록" />
</form>
- form action=”08.html” :
➡️ form태그로 action속성을 활용하여 이동할 페이지를 지정할 수 있음 - <label for=name”>이름</label>
➡️for속성으로 밑의 input태그와 연결됨 - <input type=”text” name=”name” id=”name” /><br/>
➡️브라우저의 서버쪽에서는 이 name이라는 속성이 중요하다 이 속성을 통해서 값을 꺼내게 된다. - <input type=”submit” value=”등록”/>
➡️타입으로써 submit을 지정하면 이 것이 눌렸을때 form에서 정의했던 action 경로로 이동하게된다.
<script>
const inputName = document.getElementById("name");
const inputPw = document.getElementById("password");
const inputCheckPw = document.getElementById("checkPassword");
const form = document.getElementById("myForm");
function validation(event) {
event.preventDefault();
const nameValue = inputName.value.trim();
const pwValue = inputPw.value.trim();
const checkPwValue = inputCheckPw.value.trim();
if (nameValue === "") {
alert("이름을 입력하세요!");
return;
}
if (pwValue === "") {
alert("비밀번호를 입력하세요!");
return;
}
if (pwValue !== checkPwValue) {
alert("비밀번호 확인이 일치하지 않습니다.");
return;
}
alert("정상적으로 회원가입 되었습니다!");
form.submit();
}
form.addEventListener("submit", validation);
</script>
- getElementById(”name”)
➡️inputName 값만으로 비교로직을 수행한다면 DOM객체가 비교되기때문에
input 안에 입력된 “값”들이 비교되진 않을 것이다.
➡️해결방법 : .value 로 값을 꺼내주어야한다. - const nameValue = inputName.value.trim();
➡️.value : DOM객체에 입력된 값을 꺼낸다.
➡️trim() 함수 : 이 함수를 이용하여 입력된 값의 “공백”을 제거한 후 변수에 담는다.
trim()함수는 앞뒤의 공백을 제거해주는 기능을 한다. ex. (”공백 비밀번호입니다.”) (”공백공백 비밀번호입니다.”)
이 둘은 다른 값으로 취급되어야하므로 공백을 제거하여 유효한 값만 비교할 수 있도록 도와준다. - event.preventDefault();
➡️이 기능은 기본 동작인 페이지 이동을 막음
➡️유효성을 검사하여 제대로 입력되지 않으면 페이지 이동을 막기 위해서 사용하는 문법 - form.submit() :
➡️ 전체적인 유효성 검사를 마치고 정상적으로 확인이 되었다면 form에 submit()으로 전달
if (nameValue === "") {
alert("이름을 입력하세요!");
nameValue.focus(); // 커서를 이 태그에 둘 수 있게함
return;
}
if (pwValue === "") {
alert("비밀번호를 입력하세요!");
pwValue.focus(); // 커서를 이 태그에 둘 수 있게함
return;
}
if (pwValue !== checkPwValue) {
alert("비밀번호 확인이 일치하지 않습니다.");
checkPwValue.focus(); // 커서를 이 태그에 둘 수 있게함
return;
}
- focus() :
➡️원하는 요소에 커서를 위치시킬 수 있도록 함
➡️유효성 검사가 수행되지 않은 부분에다가 커서를 두어 그 부분부터 입력을 다시 할 수 있도록 유도할 수 있는 기능
🚀실습 - Todo List
<body>
<ul id="todoList">
<li>할일1</li>
<li>할일2</li>
<li>할일3</li>
<li>할일4</li>
<li>할일5</li>
</ul>
<label for="todo">오늘의 할 일</label>
<input type="text" name="todo" id="todo" />
<button id="uploadTodo">업로드</button>
<script>
// 1. 할일들을 클릭했을때 alert로 할일1 처럼 출력
// 2. 입력을 했을때 할일들의 맨 밑에 계속 추가되는 것 구현
const parent = document.getElementById("todoList");
const uploadBtn = document.getElementById("uploadTodo");
function createTodo() {
const myTodo = document.getElementById("todo").value.trim();
const addList = document.createElement("li");
addList.innerHTML = myTodo;
parent.appendChild(addList);
}
// 1. 할일 클릭 시 할일 alert 출력
parent.addEventListener("click", (e) => {
alert(e.target.innerHTML);
});
// 2. 할 일 입력 시 할 일 리스트의 밑으로 계속 추가
uploadBtn.addEventListener("click", createTodo);
</script>
</body>
- const parent :
➡️<li> 태그들의 부모역할을 하는 <ul>태그를 가져와 직관적으로 보기 위해 parent라는 변수명사용 - const uploadBtn :
➡️업로드 버튼을 눌렀을 경우의 이벤트를 작성하기 위해 객체를 가져옴 - const myTodo :
➡️”todo”라는 input 태그를 가져와서 value.trim()으로 그 안에 있는 입력 값을 공백을 제거해 저장 - const addList = document.createElement(”li”) :
➡️<li> 태그를 하나 만들어냄 - addList.innerHTML = myTodo;
➡️방금 추가한 <li> 태그의 텍스트를 innerHTML을 이용하여
input태그로부터 가져온 입력값이 담긴 myTodo로 갱신해줌 - parent.appendChild(addList);
➡️수정한 <li>태그를 부모역할의 <ul>태그의 자식태그로 추가함 - alert(e.target.innerHTML);
➡️<ul>안에 <li>들이 속해있으므로 <ul>의 id값을 통해 만들어낸 parent변수에 이벤트를 추가함
그 이벤트로 클릭이 되었을때 alert() 알림을 띄운다.
➡️e.target : 이벤트가 발생한 부분의 객체를 받아오고
➡️innerHTML : 그 객체의 텍스트 부분을 alert()로 띄우게된다. - 💡이벤트 버블링을 이용하면 이러한 계층구조에서 이벤트 전파를 쉽게 구현할 수 있다.
만약 부모역할의 <ul> 태그에 이벤트를 걸지 않고
자식태그인 <li> 태그들에 직접 이벤트를 생성한다면
// 1. 할일 클릭 시 할일 alert 출력 (li태그에 직접 구현)
const list = document.getElementsByTagName("li");
for (let i = 0; i < list.length; i++) {
list[i].addEventListener("click", (e) => {
alert(e.target.innerText);
});
}
- 새롭게 추가하는 <li>태그들에게는 이벤트가 할당되지 않는다.
- 기존의 <li>태그들의 length 만큼만 수행하였기때문이다.
- 따라서 이벤트를 걸어주는 주체를 <li>에 걸지 않고 상위 요소인 <ul>태그에 걸어주는 것이다.
🚀 이벤트 처리를 배우면서 원하는 기능들이 직관적으로 보이다보니 재미를 느낄 수 있었다.
회고를 통해 이벤트 버블링과 캡처링을 좀 더 이해할 수 있었고
이벤트를 처리할때 화살표함수에서의 this 사용 금지, focus()를 통해 포커스를 가져가는 부분 등에서
디테일한 부분을 많이 느낄 수 있었다.
'Recording > 멋쟁이사자처럼 BE 13기' 카테고리의 다른 글
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_29일차_"useState, useRef" (0) | 2025.01.13 |
---|---|
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_28일차_"리액트 React" (1) | 2025.01.10 |
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_26일차_"자바스크립트 비동기처리" (0) | 2025.01.08 |
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_25일차_"자바스크립트 함수와 배열" (0) | 2025.01.07 |
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_24일차_"자바스크립트" (0) | 2025.01.06 |