【JS】querySelectorAll() 메조드 사용시 addEventListener() 메조트가 움직이지 않았다

문제


querySelectorAll() 메조드에서 셀렉터를 지정해, addEventListener() 메조드로 클릭 이벤트를 넣으려고 했을 때입니다.

main.js
  const target = document.querySelectorAll('nav a');
  const closeNav = function () {
    const close = document.getElementById('global-nav');
    close.classList.toggle('nav-open');
  };
  target.addEventListener('click', closeNav);
addEventListener() 가 움직이지 않는다…

Console에서는 이렇게 화가났습니다.

Uncaught TypeError: target.addEventListener is not a function
분명히 target.addEventListener가 함수로 인식되지 않는 것 같습니다.
querySelector() 그럼 잘 움직였는데…

원인



우선 querySelectorAll() 메조드의 참조를 읽으면

Document 의 querySelectorAll() 메소드는, 주어진 CSS 셀렉터에 일치하는 문서중의 요소의 리스트를 나타내는 정적인 (살아 있지 않은) NodeList 를 돌려줍니다.

그리고 있습니다.
문서의 요소 목록을 나타내는 정적 (살아 있지 않은) NodeList 반환 ...

게다가 querySelectorAll() 메조드의 반환값이라고 하는 NodeList
NodeList 객체는 노드의 집합이며, Node.childNodes 등의 프로퍼티나 document.querySelectorAll() 등의 메소드의 반환값으로서 이용됩니다.

NodeList 는 Array 와는 다릅니다만, forEach() 메소드로 처리를 반복 적용하는 것은 가능합니다. Array.from() 을 사용하여 Array로 변환할 수 있습니다.

그리고있었습니다.
이것으로부터, querySelectorAll() 의 반환값은 배열은 아니지만 리스트상으로 되어 있어, forEach() 메조드를 사용하면 처리할 수 있다고 하는 해석에 있거나 했습니다.

해결



main.js
  const targetList = document.querySelectorAll('nav a');
  const closeNav = function () {
    const close = document.getElementById('global-nav');
    close.classList.toggle('nav-open');
  };
  targetList.forEach(function (target) {
    target.addEventListener('click', closeNav);
  });

우선 querySelectorAll() 메조드의 반환값은 리스트라고 하는 것으로, targetList 라고 하는 변수명으로 했습니다.
그리고 targetList 안의 하나의 요소에 addEventListener() 메조드가 실행되도록 forEach() 메조드에서 targetList 를 돌렸습니다.

무사히 에러가 해소되어 원하는 움직임을 해주게 되었습니다.

요약


  • querySelectorAll() 메조드는 배열이 아니지만 목록의 NodeList를 반환합니다.
  • forEach() 메조드에서 리스트의 내용 하나하나에 처리를 대할 수 있다.

  • 참조


  • MDN web docs - EventTarget.addEventListener()
  • MDN web docs - Document.querySelectorAll()
  • MDN web docs - NodeList
  • 좋은 웹페이지 즐겨찾기