핀테크 서비스 프론트엔드 개발자 취업 완성 2기/JS

[JS] JavaScript에서 querySelectorAll Elements에 클릭 이벤트 적용하기. with. classList.add() & classList.remove()

flyda 2022. 4. 22. 16:25

1. 내가 원하는 시나리오!!

화면에 2021년도의 내용이 표시가 된다. 

만약 내가 2020을 클릭하면 밑의 사진처럼 2020년의 내용이 표시되게 만들고 싶다! 

내용은 html파일에 직접 넣는 것이 아니라 javascript를 통해서 넣고 싶다. 그 기능을 만들기 위해서 클릭된 연도에 active라는 클래스를 추가하도록 만들 예정이다. 

 

2. 과정_1

<ul class="timeline">
  <li class="year" data-year='2021'></li>
  <li class="year" data-year='2020'></li>
  <li class="year" data-year='2019'></li>
  <li class="year" data-year='2018'></li>
  <li class="year" data-year='2017'></li>
  <li class="year" data-year='2016'></li>
  <li class="year" data-year='2015'></li>
  <li class="year" data-year='2014'></li>
  <li class="year" data-year='2013'></li>
</ul>

나는 year 클래스를 가진 li 중 하나를 클릭하면 data-year에 있는 년도가 출력되는 코드를 만들고 싶다. 

그래서 처음에는 querySelectorAll을 통해서 모두를 선택한 뒤 addeventListener을 넣었다. 

const yearActiveEls = document.querySelectorAll('.year')

yearActiveEls.addEventListener('click', function () {
  console.log(yearActiveEls.dataset.year)
})

하지만 `timeline.js:4 Uncaught TypeError: yearActiveEl.addEventListener is not a function`이라는 에러가 났다.... 

 

그래서 이렇게 그냥 querySelector로 선택하니 당연하게 제일 위에 있는 2021만 선택할 수 있었다. ㅎ 

const yearActiveEl = document.querySelector('.year')

yearActiveEl.addEventListener('click', function () {
  console.log(yearActiveEl.dataset.year)
})

//2021

 

그래서 forEach를 사용하는 방법for문을 사용하는 방법을 찾았는데, 어제 for 문을 배워서 그냥 for 문으로 선택했다. 절대.. 갑자기 forEach문법을 잘 모르겠어서 그런게 아니다...!!!(사실은 처음에 `[]. forEach`를 보자마자 백스텝을 밟았다.

그리고 for( const el for els) 라는 새로운 문법도 신기했다. 자세한 사용법은 공식 문서를 참고하길 바란다. 

 

고친 코드는 다음과 같다!! 

1-1. 중간 성공 코드

다음 코드는 2021을 클릭하면 클릭한 년도를 콘솔창에 출력해주는 코드이다. 

const yearActiveEls = document.querySelectorAll('.year')

for (const yearActiveEl of yearActiveEls) { // 반복 가능한 객체에 대해서 반족하는 문법!! 
  yearActiveEl.addEventListener('click', function () {
    //isActiveYear = !isActiveYear
    console.log(yearActiveEl.dataset.year)
  })
}

이제 li요소를 클릭하면 해당 data-year에 들어있는 값이 나온다!! ㅎㅎㅎ 성공!!!  혹시 data-year이 무엇인지 모른다면 공식문서를 참조하길 바란다. 

 

2. 과정_2

이제 바로 바로 클래스 추가만 해주면 성공!!!인 줄 알았지만, click이벤트를 실행한 뒤 active 클래스를 추가한 뒤 다른 년도를 클릭해도 active가 사라지지 않았다.  무조건 클릭을 통해서 클래스를 없애 주어야 했다. 아니면 클릭했던 모든 li 태그에 active 클래스가 추가되는 문제가 있었다.  

당연히... 2021을 클릭하면 이전에 클릭한 2020에 active가 사라질 줄 알았는데.. ㅠㅠㅠ 너무 슬퍼.... 

const yearActiveEls = document.querySelectorAll('.year')
let isActiveYear = false;

for (const yearActiveEl of yearActiveEls) { // 반복 가능한 객체에 대해서 반족하는 문법!! 
  
  yearActiveEl.addEventListener('click', function () {
    isActiveYear = !isActiveYear
    if (isActiveYear) {
      // active 클래스 추가
      yearActiveEl.classList.add('active')
    }
    else {
      // active 클래스 제거
      yearActiveEl.classList.remove('active')
    }
    console.log(yearActiveEl.dataset.year)
  })
}

혹시 이게 그냥 반복문이 아니라 차래로 꺼내오기 때문인가 생각했다. 그래서 2중 for문으로도 작성을 하는 등 여러 가지 방법을 시도해 보았지만 계속 class를 지우지 못했다. 

어떻게 하지 고민을 하다가 문득... 원래 2021은 자동으로 선택되어 있고, 다른 것을 클릭하면 바뀌어야 하는 것 같다는 생각이 들었다. 그래서 코드를 바꾸어 보았다. 

 

3. 성공!  

완성 html 코드

<ul class="timeline">
  <li class="year active" data-year='2021'></li>
  <li class="year" data-year='2020'></li>
  <li class="year" data-year='2019'></li>
  <li class="year" data-year='2018'></li>
  <li class="year" data-year='2017'></li>
  <li class="year" data-year='2016'></li>
  <li class="year" data-year='2015'></li>
  <li class="year" data-year='2014'></li>
  <li class="year" data-year='2013'></li>
</ul>

 

완성 js 코드

// HISTORY TIMELINE
const yearEls = document.querySelectorAll('.year')
let isActiveYear = false;


for (let i = 0 ; i < yearEls.length ; i += 1 ) { // 반복 가능한 객체에 대해서 반족하는 문법!!   
  yearEls[i].addEventListener('click', function () {
    isActiveYear = !isActiveYear  
    if (isActiveYear) { // 클릭되었다면!! 
      // 먼저 현재 active 되어있는 객채를 찾아준다. 제일 처음에는 2021을 찾을 것이다!!
      let findActiveEl = document.querySelector('.active')
      // 현재 active 가 있는 요소에서 active 클래스를 제거해준다!
      findActiveEl.classList.remove('active') 
      // 클릭한 요소에 active 클래스를 추가한다!! 
      yearEls[i].classList.add('active')
    }
  })
}

 

정말 삽질 많이 했지만, 그래도 결국에는 성공해서 다행이다. 강사님이 한글로 어떤 코드를 쓰고 싶은지 써보고 코드를 짜라고 했는데, 정말 한글로 어떻게 돌아갈지 주절주절 말하고 난 다음에 코드를 고쳐보니까 코드가 왜 안 돌아가는지 알 수 있었다. 휴..^^ 

이제... 내용을 넣어야한다... 산 넘어 산 같지만 파이팅이다!!!