css 메뉴 선택시 메뉴색깔 변경하기 html공부와 함께 해야 하는 것이 바로 css입니다. css 가 정말 어렵죠;;; 이걸 못하면..다음 학습을 하기 힘든 것 같습니다. 물론 어디까지나 개인적인 견해일 뿐입니다. 모두가 적용이 되는 것은 아니죠. 그럼 이 css와 script를 이용한 간단한 메뉴 선택시 선택된 메뉴 색깔 변경하는 방법에 대해서 알아볼려고 합니다. 결과물은 위와 같습니다. 리스트1 ~8 까지 정렬된 메뉴이지요. 메뉴는 통상 li 로 많이 사용을 하더라구요. '리스트6' 을 선택하게 되면 색깔이 변경이 되는 것입니다. 또 다른 리스트를 선택하면 그 선택된 메뉴에 색이 변경이 되는 것이구요. body부분은 굉장히 쉽네요. li를 이용한 메뉴를 정리하면 됩니다. 저도 div를 사용하는 것이 굉장히 줄일려고 노력을 하는대요. 아직은....짜다보면 div가 많아지네요. 여튼 메뉴리스트이니..이 부분만 정리해보도록 하겠습니다. 스타일 부분부터가 인제 머리를 써야 하는 것 같은데요. ul, li 부분에 대해서 리셋을 먼저 진행을 하구요. li.on 부분에 대해서 red로 칼라를 지정해 둡니다. 이 부분이 바로 스크립트에서 이용이 될 css 부분이거든요. 이게 몇가지 유형을 아예 외워버려야 할 것 같습니다. 그게 편하겠어요. 아휴 초보다 보니..할 때마다..찾아야 하구..그래서 내용을 정리해 보는 것입니다. 간단하게 끝나는 것이지만 매우 유용하게 사용되고 있는 메뉴 선택입니다. 스크립트입니다. 정해둔 li 에 선택을 addclass('on') 이 받게 되네요. .on 클레스에 경우 스타일에서 red라는 css효과를 적용하게 되네요. 이것으로 선택된 메뉴에 색이 변경이 됩니다. javascript를 이용해서 '클릭하면 해당 버튼의 색깔을 바꾸는 실습'을 해볼 겁니다. 학습의 차원에서 해당 실습에 대한 여러 가지 방법을 나열하려고 합니다. 아래의 사진은 메뉴 버튼을 클릭했을 때 버튼의 색깔이 바뀌어지는 결과를 캡쳐해둔 것입니다. 방법 1)(스크립트를 중점적으로 보세요)
코드 해석맨 아랫줄 for문을 보면 menuLink를 통해서 각 메뉴 변수에게 이벤트(click)가 실행되면 함수를 추가하는 모습을 볼 수 있습니다. clickMenuHandler함수는 버튼의 색깔을 오렌지 색으로 바꾸는 class인 'menu-active'를 추가해주어야 하는데요. 여기서 this라는 객체를 통해서 누른 버튼에다가 menu-active를 추가해주어야겠지요. 하지만 this.classList.add('menu-active')를 써주었다고 해서 완성되는건 아닙니다. menu 1 버튼을 누르고 menu 2 버튼을 이어서 클릭했을 때 이런 화면을 볼 수 있습니다. 아까 눌렀던 menu 1의 menu-active가 계속 남아있는 것을 확인할 수 있습니다. 그렇다면 어떻게 해야 클릭한 해당 버튼 색깔을 오렌지 색으로 바꿀 수 있을 까요? 정답은 없습니다. 아주 많은 다양한 방법들이 있을 것입니다. 먼저 방법 1)은 '이벤트 함수가 실행될 때, 해당 class를 일일히 모두 없애버리기' 방법을 생각해보았습니다. 먼저 클릭과 동시에 이벤트 함수에서는 for문을 이용해서 모든 메뉴의 menu-active의 classList를 지우고 시작하는 방법이 있겠죠? 그 다음 클릭한 메뉴에만 클래스를 다시 추가해주는 겁니다. 하지만 이 방법은 비효율적이라고 볼 수 있습니다. 쓸데없는 for문의 반복이 많기 때문입니다. 만약 버튼이 10000000개라면 for문으로 오렌지 색깔이 적용된 클래스를 일일이 찾아서 삭제하는 것이 얼마나 많은 시간을 소비되게 할까요? 방법 2)
코드 해석앞서 방법 1)에서는 for문의 사용으로 비효율적이었다는 것을 알았죠? 그럼 이런 생각을 해볼 수 있습니다. 이벤트 함수가 실행될 때, menu-active가 적용된 class를 찾아 없애버리기 먼저 clickMenuHandler함수가 실행될 때, querySelector속성을 이용하여 ''menu-active'의 클래스를 찾아야 합니다. 그 다음 찾은 menu-active의 클래스를 지워주면 되겠죠. 이때 if문을 사용할 것을 주의하시기 바랍니다. if문을 사용하지 않고 그냥 activeMenu.classList.remove('menu-active'); 한다면 에러가 납니다. 에러의 내용은 Uncaught TypeError: Cannot read property 'classList' of null 따라서 if문을 사용하여 이 값이 존재하는지 존재하지 않은지 먼저 확인하는 작업이 필요하답니다. 그러나 이 방법도 역시 아주 좋다고 할 수 없습니다. querySelector자체가 dom을 다 뒤져야 하기 때문이죠. 방법 3-1)
코드 해석앞서 방법 2)에서는 querySelector 자체가 dom을 다 뒤져야 하기 때문에 단점이 여전히 존재함을 확인하였습니다. 방법 3)은 dom에 의존적이지 않은 방법에 대해서 살펴보겠습니다. 이때는 '현재 활성화된 메뉴를 담을 변수'를 이용해보겠습니다. 변수 이름은 'currentMenu'라고 정의해줍니다. 일단 시작할 때 currentMenu의 값은 아무것도 들어 있지 않으므로 if문을 이용해 check가 필요하겠죠? 방법 3-2)
코드 해석방법 2)와 같이 먼저 if문으로 변수 check를 하면 시작할 때 아무런 에러 없이 작동되는 것을 확인할 수 있습니다. 그 다음 this를 통해 클릭한 객체에다가 'menu-active'인 클래스를 추가하도록 코드를 작성하시구요. 이 this는 다시 '현재 활성화된 변수인 currentMenu'에 담아주도록 합니다. 현재 클릭하고 작동되는 클래스가 이 변수 안에 담아 있다는 것을 알 수 있겠죠? 그렇다면 이 방법은 querySelector로 dom을 뒤지지 않아도 변수에 담아있음을 활용하여 더 빠르고 효율적으로 실행할 수 있습니다. 하지만 마지막 줄에 for문이 조금 걸리는군요. 방법 1)에서와 마찬가지로 만약 메뉴가 백만 개라면 일일히 다 돌려서 이벤트가 실행되면 이벤트 함수를 걸어줘야 하는 단점이 있었습니다. 이제 마지막으로 이 방법을 어떻게 개선하면 좋을지 다음 포스트에서 살펴보겠습니다. |