12. Javascript. 실습 이벤트를 이용한 Menu 구현

2022. 11. 15. 01:15JavaScript

목차
1. Menu 구현하기

  1.1. HTML 구성
  1.2. CSS 구성
  1.3. Javascript 구성
2. 버블정렬(Bubble Sort)

 


1. Menu 구현하기

 

메뉴에 커서를 올리면 서브메뉴가 나오도록 만들어보자.

 

*구현순서*

  1. HTML : 메뉴에 커서를 올리면 서브메뉴가 나오도록 만든다.
  2. HTML : `li`안에 `ul, li`를 넣어 한 번에 나오도록 HTML을 구성한다.
  3. CSS : 취향껏 구성하되, 어느 부분에서 `display: none;`을 주어 숨겨놓을지 선택해야한다.
  4. Javascript : 부여된 CSS를 생각해서 이벤트를 줄 엘리먼트 잘 생각하기.

 

1.1 HTML 구성

 

li 안에 ul, li로 서브메뉴를 넣어 한 번에 나오도록 HTML을 구성했다.

<div id="wrap">
    <div id="header">
        <h1>
            <a href="#">Logo</a>
        </h1>
        <ul id="gnb">
            <li>
                <a href="#">메뉴1</a>
                <ul class="snb">
                    <li><a href="#">서브메뉴1-1</a></li>
                    <li><a href="#">서브메뉴1-2</a></li>
                    <li><a href="#">서브메뉴1-3</a></li>
                    <li><a href="#">서브메뉴1-4</a></li>
                </ul>
            </li>
            <li>
                <a href="#">메뉴2</a>
                <ul class="snb">
                    <li><a href="#">서브메뉴2-1</a></li>
                    <li><a href="#">서브메뉴2-2</a></li>
                    <li><a href="#">서브메뉴2-3</a></li>
                    <li><a href="#">서브메뉴2-4</a></li>
                </ul>
            </li>
            <li>
                <a href="#">메뉴3</a>
                <ul class="snb">
                    <li><a href="#">서브메뉴3-1</a></li>
                    <li><a href="#">서브메뉴3-2</a></li>
                    <li><a href="#">서브메뉴3-3</a></li>
                    <li><a href="#">서브메뉴3-4</a></li>
                </ul>
            </li>
            <li>
                <a href="#">메뉴4</a>
                <ul class="snb">
                    <li><a href="#">서브메뉴4-1</a></li>
                    <li><a href="#">서브메뉴4-2</a></li>
                    <li><a href="#">서브메뉴4-3</a></li>
                    <li><a href="#">서브메뉴4-4</a></li>
                </ul>
            </li>
        </ul>
    </div>
    <div id="visual">
        <h1>Visual 영역입니다</h1>
    </div>
</div>
<script src="./index.js"></script>

 

 

1.2 CSS 구성

 

각 부분에 취향껏 CSS를 주었고, class="on"이 붙었을 때 나올 화면을 미리 구성해놓는다.

* {
    margin: 0;
    padding: 0;
}

ul, li {
    list-style: none;
}

a {
    text-decoration: none;
}

#wrap {
    width: 100%;
}

#header {
    position: absolute;
    /* header안의 태그들 정렬 */
    display: flex;
    width: 100%;
    justify-content: space-between;
    text-align: center;
    /* 최소 높이를 설정해준다 */
    min-height: 100px;
}

#header > h1 {
    width: 10%;
}

#header > #gnb {
    /* gnb안의 태그들 정렬 */
    display: flex;
    width: 80%;
    padding: 20px 0;
    /* 박스들 주위에 일정하게 공간생성 */
    justify-content: space-around;
}

#header > #gnb:after {
    content: "";
    width: 100%;
    height: 200px;
    top: 60px;
    position: absolute;
    background: #fff;
    border-bottom: 1px solid #e1e1e1;
    box-shadow: 0px 10px 10px 0 rgba(50, 50, 50, 0.5);
    display: none;
}

/* gnb안의 li와 같이 움직일 수 있도록 */
#header > #gnb > li > .snb {
 position: relative;
 display: none;
 padding: 20px 0 0 0;
 z-index: 3;   
}

/* class="on"이 부여 되었을 때 출력 */
#header > #gnb.on > li > .snb {
    display: block;
}

/* class="on"이 부여 되었을 때 출력 */
#header > #gnb.on:after {
    display: block;
}

#header > #gnb > li > .snb > li + li {
    padding: 20px 0 0 0;
}

#visual {
    padding: 100px 0 0 0;
}

 

 

1.3 Javascript 구성

 

Javascript의 구성은 간단하다. class="on"을 어디에 붙였다가 떼야하는지만 알면 어려운 구성이 되지 않는다.

 

다만, 구현할 때 영역에 이벤트가 잘 먹히는 지 console.log 등을 찍어서 확인을 하고, 문제점을 확인한다.

 

구현시 첫 번째로 발생한 문제는 "mouseout"이 영역 사이사이 발생하였다.

 

그 원인은 id = "gnb"라는 영역이 생각보다 작아서 발생했다. 

 

gnbs를 선언하여 각각의 li에  "mouseover" 이벤트를 부여하고, header 영역에 "mouseout" 이벤트를 부여한다.

 

- header 영역의 높이를 css에서 가변적(min-height: 100px;)으로 주어 해결해야했다.

- 이 때, visual부분이 밀리는 문제는 visual에 padding이나 margin을 주어 해결했다.

const header = document.querySelector("#header") // header를 선택하는 선택자
const gnb = document.querySelector("#gnb") // gnb를 선택하는 선택자
const gnbs = document.querySelectorAll("#gnb > li") // gnb안의 li들을 모두 선택하는 선택자.

for(let i = 0; i < gnbs.length; i++){
    gnbs[i].addEventListener("mouseover", function(){
        gnb.classList.add("on")
    })
} //gnb에 주게되면 하위 엘리먼트마다 이벤트가 적용된다.

header.addEventListener("mouseout", function(e){
    if( e.target.id === "gnb"){
        gnb.classList.remove("on")
    }
})
// header영역에서 나가게 되면 "on"이 사라진다.
// e.target.id === "gnb"를 주어 불필요한 이벤트 발생을 막는다.

2. 버블정렬(Bubble Sort)

  •  바로 다음 인덱스의 값과 비교하여 조건에 따라 한 자리씩 바꾸어 나가는 정렬방법.

버블 정렬을 위해서는 몇 가지 단계가 필요하다.

 

우선, 배열의 순서대로 2자리 씩 번갈아 가면 출력해야한다. 나중에 두 자리씩 비교를 해야하기 때문이다.

let sortArr = [5, 3, 1, 6, 8, 7, 2, 4]

for(let i = 0; i < sortArr.length-1; i ++){
    console.log(sortArr[i], sortArr[i+1])
}
/*
5 3
3 1
1 6
6 8
8 7
7 2
2 4
*/

 

 

이제 두 숫자를 비교해서 차근차근히 넘겨줄텐데, 이때 처음부터 끝까지 두 개씩 비교하는 한 바퀴를 돌게되면 가장 큰 숫자가 가장 오른쪽으로 갈 것이다. 그렇게 되면 끝의 숫자는 더 이상 비교하지 않아도 된다. 이런 이유로 한 번 비교할 때 마다 한 번씩 비교하는 숫자를 줄여 나가야한다. 아래와 같이 코드를 구성하면, 점점 줄어들게 횟수가 찍힌다.

 

두 번째, for 문의 종료조건을 한 번 살펴보자. 배열의 횟수를 돌때마다 첫번째 for문의 i를 이용하여 줄여준다는게 핵심이다.

let sortArr = [5, 3, 1, 6, 8, 7, 2, 4]

for(let i = 0; i < sortArr.length - 1; i++) {
    for(let j = 0; j < sortArr.length - i - 1; j++) {
        console.log(sortArr[i], sortArr[i + 1])
    }
}
//7회; 5 3
//6회; 3 1
//5회; 1 6
//4회; 6 8
//3회; 8 7
//2회; 7 2
//1회; 2 4

 

이렇게 구현할 수 있다면, 이제 마지막으로 조건을 이용해 비교를 하여 값의 자리를 바꿔 주어야한다.

 

하지만, 여기서 두 자리의 값을 바꾸는 것은 사람한테나 쉬운일이지 컴퓨터에겐 여간 어려운 일이 아니다.

하노이탑이라는 게임과 유사한 방법으로 값을 옮길 수 있다.

 

 A와 B가 있다고 가정할 때, A의 값을 B에 옮겨야한다면?

 

1. A의 값을 잠시 C라는 변수에 담아둔다. 

2. 비어있는 A에 B의 값을 집어넣는다.

3. 비어있는 B에 C의 값을 집어넣는다.

4. A와 B의 값은 바뀌어있다.

 

이 방법을 사용해 정렬을 마무리 해보자.

let sortArr = [5, 3, 1, 6, 8, 7, 2, 4]

for(let i = 0; i < sortArr.length - 1; i++) {
    let temp
    for(let j = 0; j < sortArr.length - i - 1; j++) {
        if( sortArr[j] > sortArr[j + 1]) { 
                temp = sortArr[j]
                sortArr[j] = sortArr[j + 1]
                sortArr[j + 1] = temp
            }
    }
}

console.log(sortArr) // [1, 2, 3, 4, 5, 6, 7, 8]

위의 단계를 거쳐 정렬이 잘 된것을 볼 수 있다. 정렬방법 중에 가장 이해하기가 쉬운방법이지만, 이 방법은 연산횟수가 n(n-1)/2. 즉 O(n^2)이므로 효율적인 방법은 아니다.


 

'JavaScript' 카테고리의 다른 글

14. Javascript.실습 C.R.U.D  (1) 2022.11.20
13. Javascript.실습 Counter와 C.R.U.D  (0) 2022.11.18
Javascript 슬라이드 구현  (0) 2022.11.14
10. Javascript DOM Event Loop  (0) 2022.11.11
9. Javascript DOM DOMContentLoaded  (0) 2022.11.11