addEventListener
사용법만 알았는데, 체크리스트 만들다가 이렇게 돌고 돌아 깊게 공부하게 되었다. 똑같은 문제로 하루 종일 잡고 있으니, 지치긴했는데 해결책을 알게 되었음 된거다. ( 다독다독😭 )
관련 메소드 들도 공부하고 정리 해보았다. 그렇다면, 레 - 고 ☝🏻
하위에서 상위 요소로 이벤트 전파방식을 이벤트버블링 이라고 한다.
특정 화면 요소에서 이벤트가 발생했을 때 해당 이벤트가 더 상위의 화면 요소들로 전달되어 가는 특성을 가지고 있다.
<body>
<div class="green">그린
<div class="yellow">옐로우
<div class="tomato">토마토</div>
</div>
</div>
</body>
const divs = document.querySelectorAll("div");
divs.forEach(function(div) {
div.addEventListener("click", logEvent);
});
function logEvent(event) {
console.log(event.currentTarget.className);
}
green div
, yellow div
, tomato div
를 각각 클릭하게 되면 콘솔에 찍히는 건 무엇일까 ?
여기서 궁금증 해결해보자.
한개를 클릭했을 뿐인데 3개의 이벤트가 발생한다.
왜 why ? : 브라우저가 이벤트를 감지하는 방식 때문이다.
브라우저는 특정 화면요소에 이벤트가 발생했을 때, 그 이벤트를 최상위에 있는 화면요소까지 이벤트를 전파한다. 따라서 토마토-옐로우-그린
순서로 태그에 등록된 이벤트들이 실행된다.
❗️ 주의 : 각 태그마다 이벤트가 등록되어 있기에 상위요소로 이벤트가 전달되는 것을 확인해보아야 한다.
만약, 이벤트가 특정 div
만 달려있으면 안된다. -> 뭔말이야 ?
( 이벤트 버블링, 캡쳐, 위임 이런걸 사용하지 않고, 특정 요소에게 이벤트가 정확하게 겨냥하고 있다면, 이럴 경우는 addEventListener
사용보단, 그냥 onClick()
을 사용하라는 말인 것 같다. )
이벤트 버블링과 반대방향으로 진행되는 이벤트 전파 방식이다.
const divs = document.querySelectorAll("div");
divs.forEach(function(div) {
div.addEventListener("click", logEvent, {
capture: true // default 값은 false입니다.
});
});
function logEvent(event) {
console.log(event.currentTarget.className);
}
capture
: true
: 이벤트 감지를 위해 이벤트 버블링과는 반대반향으로 탐색한다.green
가 먼저 찍힌걸 볼 수 있다.: 복잡한 이벤트 전달방식을 알고 싶지 않고, 그냥 원하는 화면 요소의 이벤트만 신경쓰고 싶을 때 사용된다.
function logEvent(event) {
event.stopPropagation(); // 이 api는 이벤트가 전달되는 것을 막는다.
}
따라서 버블링은 해당 이벤트만 발생한다. ( 상위요소 전파를 방해 )
사용법
divs.forEach(function(div) {
div.addEventListener("click", logEvent, {
capture: true // default 값은 false입니다.
});
// 생략 가능
div.addEventListener("click", logEvent, true);
});
function logEvent(event) {
event.stopPropagation();
console.log(event.currentTarget.className); // one
}
조건문을 이용해 주는것.
const green = document.querySelector('.green');
green.addEventListener('click',function(e){
const { target, currentTarget } = e;
if ( target !== currentTarget ) return
console.log("currentTarget : ", currentTarget.className);
console.log("Target : ", target.className);
})
if문
의 설명은
👉🏻 클릭한 대상의 target
과 currentTarget
이 동일하지 않다면, 클릭한 대상이 자기 자신일 때만 동작하도록 한다.
하위 요소에 각각 이벤트를 붙이지 않고 상위요소에서 하위요소의 이벤트들을 제어하는 방식
<h1>체크 리스트</h1>
<ul class="itemList">
<li>
<input type="checkbox" id="list1">
<label for="list1">이벤트 리스트 1</label>
</li>
<li>
<input type="checkbox" id="list2">
<label for="list2">이벤트 리스트 2</label>
</li>
<li>
<input type="checkbox" id="list3">
<label for="list3">이벤트 리스트 3</label>
</li>
</ul>
/*
var inputs = document.querySelectorAll('input');
inputs.forEach(function(input) {
input.addEventListener('click', function(event) {
alert('clicked');
});
});
*/
// 상위 ul tag에 이벤트 부여 , 이벤트 버블링 효과에 따라 아래 li에 요소가 추가되도 이벤트 실행 가능
var itemList = document.querySelector(".itemList");
itemList.addEventListener("click", function(event) {
// target을 이용해 클릭할 때마다, text에 style의 효과를 주었다.
event.target.style.textDecoration = !event.target.style.textDecoration ? 'line-through' : '';
});
// 새 리스트 아이템을 추가하는 코드
var itemList = document.querySelector(".itemList");
var li = document.createElement("li");
var input = document.createElement("input");
var label = document.createElement("label");
var labelText = document.createTextNode("이벤트 위임 학습");
input.setAttribute("type", "checkbox");
input.setAttribute("id", "list4");
label.setAttribute("for", "list4");
label.appendChild(labelText);
li.appendChild(input);
li.appendChild(label);
itemList.appendChild(li);
setAtttribute
를 이용해 id
type
for
를 지정해준다.이 부분을 체크리스트에서 input
에 입력칸을 만들어서 사용하면 될 것같다.
addEventListener
클릭이벤트에서는 체크리스트를 제일 크게 감싸고 있는 ul
태그에 addEventListener
를 이용해 클릭을 했을 때, 처리되는 화면의 기능을 넣어주었다.
각 요소마다 addEventListener
를 걸어 주는 방법을 사용하거나, (
주석처리 부분은 이벤트 위임을 이용하지 않은 전의 작업처리이다. ) 각 리스트인 input
을 모두 찾아 forEach()
로 돌려주고 이벤트를 걸어주게 되면, 코드가 굉장히 지저분 하고 비효율적일 것이다.
많은 걸 알았다.
빨리 진도 나가야되겠다.
나도 얼른 잘 만든 코드를 만들고 싶다. 발전하자!
그럼 이만 - 🙌🏻
유용해서 자주 이용하는 블로그다.😀😀😀😀😀👍🏼👍🏼👍🏼
참고한 사이트