잿꽃's posting Garden

2차메뉴 이상일 때 자바스크립트로 클릭 이벤트를 만드는 두 가지 방법 본문

WEB/JAVASCRIPT

2차메뉴 이상일 때 자바스크립트로 클릭 이벤트를 만드는 두 가지 방법

잿꽃 2022. 3. 25. 01:38

 

자바스크립트로 메뉴를 두 가지 방법으로 만들어 보자.

 

for문과 forEach문을 이용할 것이기 때문에 두 가지 방법이지만 사실상 같은 방법이다.

 

 

1. forEach문으로 만든 메뉴

알고리즘

1. 한 인자에 메뉴 전체 값을 담는다.

2. 이벤트를 각자 적용하기 위해 forEach함수를 이용하여 배열로써 작동할 수 있게 한다.

3. 해당하는 아이템이 클릭되면 불리안 값의 인자가 토글되게 한다.

4. 참이면 인덱스의 값이 해당 인자의 배열 순서로 들어가고 클래스를 부여한다.

5. 거짓이면 클래스를 제거한다.

 

let toggle = false;
const mainmenuClick = document.querySelectorAll('header .mobile .total-menu .menu-box .mainmenu');

mainmenuClick.forEach(function(item, index){
    item.addEventListener('click',()=>{
        toggle = !toggle;
        if(toggle){
        mainmenuClick[index].classList.add('active');
        }
        else{
        mainmenuClick[index].classList.remove('active');
        }
    });
});

 

forEach문에서 모든 메뉴가 있는 mainmenuClick값을 배열로써 받았다.

item에 해당하는 것은 mainmenuClick[0], mainmenuClick[1], mainmenuClick[2].... 이 될 것이고

index에는 위의 item개수(=메뉴개수)에 따라 0, 1, 2... 이렇게 값이 될 것이다.

이벤트 리스너를 통해서 이 배열의 각자 값이 클릭되었을 때마다 인자의 값이 토글되면서 active라는 클래스가 추가되었다가 제거되었다가 할 수 있다.

css에서 active값을 가지면 display : block으로 설정하여 보일 수 있게 작성하였다.

 

>>문제<<

해당 메뉴만을 클릭하면 작동이 잘 되지만 해당메뉴를 1회 클릭하여 active 상태가 되었을 때 다른 메뉴를 클릭하면 toggle값이 변하였기 때문에 다른 메뉴를 펼칠 때에는 2회를 클릭해야 된다.

>> 현재 값이 active의 클래스 값을 가지고 있으면이라는 코드가 필요할 것 같다.

>> classList.contains('active')를 이용한 코드가 추가적으로 필요해 보인다.

const mainmenuClick = document.querySelectorAll('header .mobile .total-menu .menu-box .mainmenu');

mainmenuClick.forEach(function(item, index){
    item.addEventListener('click',function(e){
    	e.preventDefault();
        if(mainmenuClick[index].classList.contains('active')){
            mainmenuClick[index].classList.remove('active');
        }else{
        mainmenuClick[index].classList.add('active');
        }
    });
});

라고 수정하였다.

 

 

 

2. for문으로 만든 메뉴

위의 문제를 반영하면서 for문으로 메뉴를 작성하였다.

 

알고리즘

1. 한 인자에 메뉴 전체 값을 담는다.

2. for문을 이용하여 모든 메뉴의 배열 값에 click이벤트가 작동할 수 있게 할 수 있게 한다.

3. 현재 부모노드에 클래스가 있으면 제거한다.(같은 메뉴를 눌렀을 때 펼치고 접히는 기능)

4. 클래스가 없으면 모든 메뉴의 클래스를 제거하고 현재 부모노드에 클래스를 추가한다.(현재 메뉴를 눌렀을 때 다른 메뉴가 닫히는 기능)

const toggles = document.querySelectorAll('.toggle');

for(let i =0; i < toggles.length; i++){
    toggles[i].addEventListener('click', function(e){
    	e.preventDefault();
    if(this.parentNode.classList.contains('active')){
        this.parentNode.classList.remove('active');
    }else{
        for(let i = 0; i < toggles.length; i++){
            toggles[i].parentNode.classList.remove('active');
        }
        this.parentNode.classList.add('active');
    }
    });
};

 

1차박스 > 1차메뉴+2차박스가 있는 구성이기에 1차 박스에 클래스를 부여하기 위해 parentNode가 사용되었다.

1차 박스에 active가 주어지면 2차 박스의 높이가 0의 값에서 늘어나게 된다.

 

for문을 이용하여 모든 값에 click이벤트를 추가하였다.

toggles[0].addEventListener('click', function(e){...}, toggles[1].addEventListener('click', function(e){...} ....의 함수가 있는 것이다.

function(e){...}의 함수 안에 active라는 클래스 있음을 감지하여 같은 메뉴를 눌러도 펼치고 접히는데 문제가 없다.

클래스가 없다면 모든 클래스를 삭제한다.

toggles[0].parentNode.classList.remove('active');, toggles[1].parentNode.classList.remove('active'); ..... 모든 active를 삭제한다. 그리고 현재의 값에 active를 부여한다.

 

만약 1번의 형식으로 만든다면,

const toggles = document.querySelectorAll('.toggle');

toggles.forEach(function(item, index){
    item.addEventListener('click',function(e){
    	e.preventDefault();
        if(toggles[index].parentNode.classList.contains('active')){
            toggles[index].parentNode.classList.remove('active');
        }else{
        toggles[index].parentNode.classList.add('active');
        }
    });
});

라고 만들 수 있다.

728x90
Comments