본문 바로가기
웹 프론트엔드/Html, CSS, JavaScript

[JavaScript] addEventListener 작동오류 (addeventlistener is not a function)

by 알거음슴 2022. 6. 14.

특정 위치에 마우스를 올리면 버튼 색에 변화를 주려는 코드를 작성하던 중

addEventListener가 작동을 안한다..?!

 

왜그러니..?

 

원일을 파악해보니 DOM을 제어하기 위해 선언한 getElementsByClassName() 의 경우 객체를 배열로 출력하기에 발생한 문제이다.

        <div>
          <a class="navBtn" href="#">HOME</a>
        </div>
        <div>
          <a class="navBtn" href="#">SERVICE</a>
        </div>
        <div>
          <a class="navBtn" href="#">ABOUT</a>
        </div>
        <div>
          <a class="navBtn" href="#">PRICING</a>
        </div>
        <div>
          <a class="navBtn" href="#">CONTACT US</a>

class="navBtn" 을 제어하기 위해 getElementsByClassName() 사용할 경우 class에 해당하는 대상이 여럿임으로 배열로 출력이 진행된다

const navBtn = document.getElementsByClassName("navBtn")

console.log(navBtn)

 

이제 발생한 문제를 해결해보자.

 


방법 1. DOM 객체 중 1개만 활용이 필요한경우.

이는 간단하다, 배열로 선언된 객체중 하나만 뽑아와서 사용하면된다.

 

const navBtn = document.getElementsByClassName("navBtn")

console.log(navBtn)

navBtn.addEventListener("mouseover", navBtnColor); // 이게 아니라
navBtn[0].addEventListener("mouseover", navBtnColor); // 이거다!

 

방법 2. DOM 객체 중 해당 클래스에 모두 적용하고싶은 경우.

본인이 필요한 해결방안이 다음과 같았다, 방법을 찾아보니 forEach 를 활용하는 방법이 있었다.

 

array.forEach() 를 활용하여 배열 내 DOM 객체를 하나씩 뽑아와보자.

const navBtn = document.getElementsByClassName("navBtn")

console.log(navBtn)

function navBtnColor() {
  console.log("wow!")
}

navBtn.forEach((element) => {
  console.log(element);
})

또..안된다?

하지만 아쉽게도 이번에도 적용이 되지 않았다..

 

어디가 문제인지 역시나 구글의 힘을 빌려서 방법을 여럿 찾아보니 다음과 같은 답을 얻을 수 있었다.

getElementsByClassName vs querySelectorAll 둘의 차이가 있다!
두 함수 모두 DOM 의 class 명을 가져올 수 있는 함수이나 HTMLCollection 형식인지 NodeList 형식인지의 차이가 있다!
1. HTMLCollection (getElementsByClassName 사용 시)
 - live DOM 즉 객체의 상태 변화를 실시간으로 반영하는 함수.

2. querySelectorAll
 - non-live 즉 객체의 상태 변화를 정적으로 반영하는 함수.

물론 두 차이점을 아직은 이해하기 힘드나, 이중 querySelectorAll 활용 시 array.forEach 를 사용할 수 있다고 한다.
제일좋은건 두 객체 모두 배열로 변환 후 사용하는것이 권장된다고 하니 기억해두자.
=> Array.from과 스프레드 연산자를 활용하면된다.

?? 이건 몰랏네..


결론적으로 getElementsByClassName => querySelectorAll 으로 변경 후 forEach() 반복문을 활용하여 원하는 결과를 도출할 수 있었다.

 

모르는것을 그대로 받아들이기보단, 좀더 원리를 이해해야하는 상황이 점점 많이 발생된다.이해하고 받아들이자, 이해하지 못했다면 기록해서 이해할 수 있도록 여러번 확인해보도록 하자.

 

수정된 코드.

const navBtn = document.querySelectorAll(".navBtn")

console.log(navBtn)

function navBtnColor() {
  console.log("wow!")
}

navBtn.forEach((element) => {
  element.addEventListener("mouseover", navBtnColor)
})

 

내 WOW!는 잘 동작하니 마저 개발하러 가자~