본문 바로가기

WINK-(Web & App)/React.js 스터디

[2024 JS 심화 프론트 스터디] 정호용 #2주차 "JS 나머지"

반응형

-----수정-----

JS 알고리즘 문제 발표자료입니다. 발표 때 너무 복잡하게 설명 드린 것 같아 다시 정리했습니다!

JS심화스터디_알고리즘_최소공배수_정호용.pdf
0.47MB

 


지난번에 이어 이번에는 반복문, 함수, 이벤트 등 자바스크립트의 좀 더 자세한 기능들을 배웠습니다.

 

12강. 반복문

 

✅ 말 그대로 특정 작업을 계속 반복하는 작업

 

for문?

✅ 가장 널리 쓰이는 방식이다.

// 💡 변수이므로 let이 사용됨
for (let i = 0; i < 5; i++) {
  console.log(i);
}

for (변수 선언 & 할당 ; 종료조건 ; 참일 시 블록 내 코드 이후에 실행할 것){
    실행문

}

i가 0,1,2,3,4까지 1씩 증가하며 반복문을 총 5번 돌림

✅ 출력값은 0,1,2,3,4

for (let i = 10; i > 0; i -= 2) {
  console.log(i);
}

i가 10부터 0 전 까지 -2씩 감소하며, 10,8,6,4,2 총 5회 반복

✅ 출력값은 10,8,6,4,2

✅ 보통 for문의 변수는 i를 쓰는데, i는 index의 약자이다.

for (let i = 1; i <= 9; i++) {
  for (let j = 1; j <= 9; j++) {
    console.log(i + ' X ' + j + ' = ' + i * j);
  }
}

구구단을 출력하는 코드이다.

✅ i가 1일 때, j는 1부터 9까지 9번 반복한다 ...... i가 9, j가 9일때까지 반복하므로 총 81번 반복한다.

✅ 출력값은 우리가 아는 구구단이 출력된다.

for (let i = 0; i < 100; i++) {
	if (i % 3 === 0) continue; // 한 루프를 건너뜀
	if (i > 10) break; // 루프 종료
	console.log(i);
}

✅ i를 3으로 나눈 나머지가 0일 때 === i가 3의 배수일 때 이번 루프만 건너뛴다.

✅ i가 10보다 커지면 루프 자체를 탈출한다. 약간 break가 긴급 종료 느낌..?

✅ 즉, 여기서는 1,2,4,5,6,7,8,9,10까지만 출력된다.

 

const myArray = ['한놈', '두시기', '석삼', '너구리', '오징어'];

for (const item of myArray) { // 상수명은 자유
	console.log(item);
}

for (let i=0; i < myArray.length; i++){
	console.log(myArray[i]);
}

✅ 위의 for 문은 반복문을 조금 더 간편하게 만든다.

✅ for (상수 item of myArray) {

    console.log(item) // 변수 item의 이름은 자율적으로 정해도 된다.

}

✅ 변수 i 등이 변하지 않지만, 반복 한 회차를 끝날 때 마다 새로운 값이 상수로 주어진다.

 

const person1 = {
	name: '김철수',
	age: 25,
	married: false
}

for (const key in person1) {
	console.log(key, typeof key);
}



for (const key in person1) {
	console.log(person1[key]);
}

✅ 여기서 person1의 key는 name, age, married!

✅ typeof key는 전부 string이다.

✅ 위쪽 for문은 키 이름을 문자열로, 아랫쪽 for문은 얻은 키 이름을 토대로 객체의 접근하는 것이다.

✅ person1.key 처럼 하면 안되나..? undefined가 뜸! 상수 key와 person1[key] 의 key는 서로 연관이 없기 때문!

 

while?

let x = 0;

while (x < 10) {
  console.log(x++);
}
​
let x = 0;

while (x < 100) {
	const toPrint = x++;
	
	// continue와 break 역시 동작
	if (toPrint % 3 === 0) continue;
	if (toPrint > 10) break;

  console.log(toPrint);
}
​

✅ while은 for에 비해 더 간단하다!

✅ 물론 continue, break모두 동일하게 동작한다.

✅ 저기서 x증가 코드 ( const toPrint = x++; 가 없으면 무한 continue를 하게 된다. (무한~ 반복!)

 

do while? 

✅ while : 선확인 후조치 <-> do while : 선조치 후확인

let x = 12;

do {
  console.log(x++);
} while (x < 10);

✅조건에 안 맞더라도 한 번은 실행한다.

 

 

13강. 함수

 

함수?

✅ 함수란, 반복될 수 있는 작업을 정의한다. (이론적 의미)

✅ 함수란, input을 받아 output을 반환한다. (학술적 의미)

console.log('HTML로 갖다놓고');
console.log('CSS로 꾸미고');
console.log('JavaScript로 시킨다.');

✅ 위 코드를 만 번 반복한다고 생각해 보자. 함수가 필요한 이유이다.

 

function describeHtmlCssJs () {
	console.log('HTML로 갖다놓고');
	console.log('CSS로 꾸미고');
	console.log('JavaScript로 시킨다.');
}

✅ 함수 정의 부분이다.

describeHtmlCssJs();

✅ 정의한 함수를 이름 + () 로 호출할 수 있다.

일일이 console.log 찍기 함수 만들어서 간단하게 호출만 하기
console.log('HTML로 갖다놓고');
console.log('CSS로 꾸미고');
console.log('JavaScript로 시킨다.');
console.log('HTML로 갖다놓고');
console.log('CSS로 꾸미고');
console.log('JavaScript로 시킨다.');
console.log('HTML로 갖다놓고');
console.log('CSS로 꾸미고');
console.log('JavaScript로 시킨다.');
describeHtmlCssJs();
describeHtmlCssJs();
describeHtmlCssJs();

같은 작업이나, 코드가 확연히 줄어든다. 뭐가 더 쉽고 간편한가요?

 

매개변수와 인자?

// to : 매개변수
function countTo (to) {
	for (let i = 1; i <= to; i++) {
		console.log(i);
	}
}

// 5 : 인자
countTo(5);

✅ countTo에 5를 넣어준 인자는 countTo라는 함수에 들어가면서 to라는 매개변수에 넣어준다. 여기서부터는 to -> 5이다.

 

값을 반환하는 함수?

function add(x, y) {
	return x + y;
}

✅ 매개변수가 여러 개 있는 함수도 있다. 다만 너무 많이는 넣지 않는다.

✅ 이 함수는 매개변수로 들어온 x와 y를 더해서 반환해 준다.

console.log(add(2, 3));

✅ 물론 console.log() 도 함수다!

console.log(
  add(add(6, 7), add(8, 9))
);

✅ add(6,7) 먼저 수행 -> 13

✅ add(8,9) 수행 -> 17

✅ add(13,17) 수행 -> 30

 

const subt = function (x, y) {
  return x - y;
}

console.log(subt(7, 2));

✅ 함수도 특정 값처럼 여겨질 수 있다! 즉, 함수를 작성하는 법이 여러 가지가 있다. 또 다른 방법은...

 

화살표 함수?

// 한 줄 안에 값만 반환시
const mult = (x, y) => x * y;

console.log(mult(2, 7));

 x와 y의 값을 인자로 받아 서로 곱한 것을 mult에 대입한다!

// 두 줄 이상의 작업이 있을 시
const mult = (x, y) => {
  console.log(`${x}와 ${y}를 곱합니다.`);
  console.log(`결과는 ${x * y}입니다.`);
  return x * y;
};

console.log(mult(2, 7));

두줄 이상일 시 괄호를 써 주고 꼭 return 을 써줘야 한다.

 

14강. HTML요소들 선택하기

 

DOM?

✅ HTML과 CSS를 제어할 수 있는 수단

✅ getElementsByTagName : 태그명으로 검색

document.getElementsByTagName('section');

✅ 우리가 굳이 선언하지 않아도 만들어지는 document + . + getElementsByTagName(태그명) 

// 상수/변수로 저장 가능
const $listItems = document.getElementsByTagName('li');

console.log($listItems);

✅ 상수나 변수에도 저장 가능! 관례로 변수명이나 상수명 앞에 $를 붙인다.

 

✅ getElementsByClassName : 클래스명으로 검색

document.getElementsByClassName('plant');
document.getElementsByClassName('soldout');

 

✅ getElementsById : ID로 검색

document.getElementById('sweets');

 

✅ querySelector, querySelectorAll : CSS에서 쓰던 쿼리셀렉터를 그대로 쓸 수 있다.

document.querySelector('section');

✅ 해당하는 첫 번째 것만 가져온다

document.querySelectorAll('section');

✅ 해당하는 모든 걸 가져온다

document.querySelector('.plant > ul > .soldout');

✅ plant 클래스 속 ul 속 soldout

document.querySelector('#sweets ul > :nth-child(2)');

✅ 두번째 li 값

 

✅ Children

document
.querySelector('section')
.children;

자식 값 반환

 

✅ firstElementChild, lastElementChild

const $firstUl = document.querySelector('ul');

✅ 첫 ul요소 선택됨

$firstUl;
$firstUl.firstElementChild;

✅ 당근 선택

$firstUl.lastElementChild;

✅ 양파 선택

 

✅ parentElement : 부모 요소 반환

$firstUl.parentElement;

✅ section이 선택된다.

 

15강. 요소들 조작하기

✅ .querySelector

const $carrot = document
.querySelector('section > ul > li');

✅ $carrot 반환

$carrot.textContent;

✅ 접근자 -> 당근 반환

특정 요소가 이미 갖고있는 값을 받을 수 있음

특정 값을 수정할 수 있음

$carrot.textContent = '제주당근';

✅ 제주 당근으로 값이 바뀜

 

클래스 접근 classList

✅ 배열과 유사한 상태이다.

const $onion = document
.querySelector('section ui')
.lastElementChild;
$onion

 

 

✅해당 요소는 코드 상 감춰져 있지만 (hidden class), 값을 호출 가능하다.

✅또한, classList를 이용하여 onion의 클래스를 접근 가능

$onion.classList;

✅ 화살표를 펼치면 배열 같은 클래스가 반환됨을 알 수 있다.

$onion.classList.remove('hidden');

✅ hidden을 제거해 준다. (즉 여기선 숨겨져 있던 양파를 나타나게 한다.) 

✅ 다만, 페이지 소스를 보기하면 여전히 hidden 클래스가 보인다. 이것은 원본 html파일내용을 보여주는 것 일뿐이다. 

내가 적용한 코드가 적용되진 않는다.

$onion.classList.add('organic');

✅ organic이라는 클래스를 추가해 준다. (여기서는 (유기농) 이 추가된다.)

$onion.classList.toggle('soldout');

✅ 토글링 (on/off해주는 것)을 추가할 수도 있다. soldout은 반투명 해 지도록 만들어두었다. 한번 더 실행 시 토글 해제한다.

 

스타일링

 

✅ style이라는 접근자를 붙여서 css 조작 또한 가능하다.

$onion.style.fontSize;

$onion.style.['font-size'];

 

✅ JS에서 접근 시 - 는 쓸 수 없다. - 를 빼고 다음 글자를 대문자를 써 주면 된다. CSS속성 그대로 적고 싶을땐 이대로 써준다.

$onion.style['font-size']

 

✅ 즉 사용 가능한 명령어는 이와 같다.

$onion.style.fontSize = '1em';
// Camel Case 사용

$onion.style['font-size'] = '2em';
// 대괄호 접근자 사용

 

 

a태그를 제어해 보자!

const $hyperlink = document.querySelector('a')
$hyperlink;

$hyperlink.getAttribute('href');
$hyperlink.setAttribute('href', 'https://www.yalco.kr');
$hyperlink.getAttribute('href');

✅ getAttribute(속성명) : 속성값 확인 가능

✅ setAttribute(속성명, 값) : 속성값 수정 가능

 

value, checked

const $message = document.querySelector('input[name=message]');

const $toggle = document.querySelector('input[name=toggle]');


$message.value;



$message.value = '안녕하세요';

$toggle.checked;

$toggle.checked = !$toggle.checked;

✅ 입력창 토글 상수로 선언 - value로 접근 및 수정

✅ 체크박스 상수로 선언 - checked로 접근 및 수정

✅ $toggle.checked = !$toggle.checked; - 반복 실행 가능

 

removeChild

const $ul = document.querySelector('section > ul');
$ul.removeChild($onion);

// 모든 자식 요소 지우기
while ($ul.firstChild) {
  $ul.removeChild($ul.firstChild);
}

✅ 첫 문단 - onion이라는 child요소를 프로그램에서 삭제

✅ 두 번째 문단 - ul요소 아래에 자식이 들어있다면 첫 번째 자식을 지워나감 -> 즉 ul아래 자식이 빌 때 까지 자식 모두 삭제

 

createElement

const $tomato = document.createElement('li');
$tomato.textContent = '토마토';

$tomato;

✅ createElement를 이용, tomato라는 li요소를 만든다.

✅ 요소만 생성되었지, 아직은 페이지에 추가되어 있지는 않음.

 

appendChild

$ul.appendChild($tomato);

const veges = ['상추', '가지', '브로콜리'];

for (const itm of veges) {
  const $el = document.createElement('li');
  $el.textContent = itm;
  $ul.appendChild($el);
};

✅ appendChild를 이용해서 tomato를 ul안에 추가함.

✅ 배열 및 반복문을 이용해서 배열 속 아이템들을 li라는 속성으로 선언하고, ul 안에 추가해 줄 수도 있다.

 

16강. 이벤트

 

const myButton = document.querySelector('#myButton');

✅ myButton이라는 상수 선언

 

addEventListener

// 마우스 클릭 이벤트
myButton.addEventListener('click', function () {
	console.log('클릭');
});

✅ addEventListener(주어진 이벤트, 메서드의 동작); - 즉 두 가지의 인자가 필요하다.

✅ 이벤트 리스너 -> 즉 특정 이벤트 발생 시 동작을 실행시켜준다.

 

const logMouseEnter = () => { console.log('진입'); };
const logMouseLeave = () => { console.log('이탈'); };

✅ 메서드의 동작을 지정

// 마우스 진입/이탈 이벤트
myButton.addEventListener('mouseenter', logMouseEnter);
myButton.addEventListener('mouseleave', logMouseLeave);

✅ 역시 이벤트 리스너에 각각 등록해 준다.

 

이벤트 객체

const clickPosition = document.querySelector('#clickPosition');
clickPosition.addEventListener('click', function (e) {
	console.log(e);
});

// 하나의 이벤트에 여러 콜백함수 등록 가능
clickPosition.addEventListener('click', function (e) {
	let text = 'x: ';
	text += e.clientX;
	text += ', y: ';
	text += e.clientY;
	clickPosition.textContent = text;
});

✅ 위의 이벤트 리스너 안에 들어가는 함수를 콜백함수라 한다. - 다른 곳에 인자로 들어가 특정 시점에 호출되는 함수

✅ e를 콘솔에 출력 했기 때문에 이벤트 객체 출력

✅ 객체이므로, 조회 및 수정도 가능하다!

✅ 하나의 이벤트에 여러 콜백함수를 등록 가능하다.

✅ 두 번째 콜백함수에는 x와 y의 좌표를 띄우게 했다.

 

포커스와 블러

 

const myInput = document.querySelector('#myInput');

// 인풋 요소 등이 사용자 입력을 받을 준비가 된 상태
myInput.addEventListener('focus', () => {
	myInput.setAttribute('placeHolder', '포커스 온 된 상태');
});

// 포커스를 잃어 활성이 아니게 된 상태
myInput.addEventListener('blur', () => {
	myInput.setAttribute('placeHolder', '블러 된 상태');
});

// 인풋 요소의 값이 바뀔 때
myInput.addEventListener('change', (e) => {
	console.log(e.target.value)
});

// 키 입력
myInput.addEventListener('keyup', (e) => {
	console.log(e.key);
});

 

✅ focus : 입력 창 클릭하거나, 입력 시 입력창 테두리가 색깔이 바뀌는 것이 포커스

✅ blur : 입력 창 외의 것을 클릭시 입력창 테두리가 회식으로 바뀌는 것이 블러

✅ change : 인풋 요소의 값이 바뀔 때도 이벤트를 지정할 수 있다. 입력창에 텍스트를 입력하고 다른 곳을 클릭하면 출력해 준다.

✅ keyup : 키가 입력이 될 때 그 키 값이 불려온다. 즉, keyup은 키보드가 반응할 때 쓰는 이벤트이다.

 

 

마지막강. 최종 프로젝트

 

✅ 주어진 html과 css 코드에 자바스크립트 코드를 더해서 웹 사이트를 완성했다.

const headerNavs = [
    { title: '얄코강좌는', link: '#about' },
    { title: 'HTML', link: '#html' },
    { title: 'CSS', link: '#css' },
    { title: '커리큘럼', link: '#curriculum' },
    { title: '문의하기', link: '#contact' }
];

배열 안에 여러 객체가 들어 있음. 타이틀과 링크로 나뉘어짐.
✅ html에 들어가는 요소가 가변적일 수도 있음.
✅ 그래서 이와 같이 데이터 형식으로 짜놓은 뒤 이에 맞게 html태그를 생성하는것도 좋다.

 

const $headerNavUl = document.querySelector('.header__nav ul');
// 상수명이므로 $를 붙이는 것이 관례!

for (const nav of headerNavs) {
    const $li = document.createElement('li');
    // li태그 속성 추가
    $li.classList.add('header__nav-item');
    // 원래 html클래스의 태그와 동일하게 header__nav-item으로 작성
    const $a = document.createElement('a');
    // a태그 속성 추가
    $a.textContent = nav.title;
    $a.setAttribute('href', nav.link);
    // a태그에 하이퍼링크 속성 href 추가

    $li.appendChild($a);
    // li 태그 안에 a태그 넣음
    $headerNavUl.appendChild($li);
    // headerNavUI 태그 안에 li태그 넣음
}
// for...of...문 사용하면 of 뒤의 요소에서 nav의 이름으로 하나하나 가져옴

방금 위에서 선언했던 headerNavs객체를 연결해 줄거다.

✅ li태그 안에 a태그가 있고, a태그 안에 href속성이 있다.

✅ 태그는 createElement로 요소를 만들면 되고, a태그 안에 href라는 속성을 setAttribute로 추가해 준다.

✅ headerNavUI태그 안에 li태그, li태그 안에 href속성을 가진 a태그가 있기 때문에 하위 단계부터 상향식으로 추가해 준다.

✅ href속성은 이미 추가했으므로, appendChild로 a태그를 li태그에 자식으로 추가해준다.

✅ 윗줄과 동일하게 li태그를 headerNavUI 태그 안에 추가해 준다.

 

✅ 이렇게 된다!

 

이제는 about 아래 공간에 설명을 추가해 보겠다.

 

const aboutCards = [
    {
        img: './images/about_1.svg',
        title: '빠른 강의',
        descs: [
            '군더더기 없는 진행으로',
            '여러분의 시간을 절약합니다.'
        ]
    },
    {
        img: './images/about_2.svg',
        title: '손쉬운 학습',
        descs: [
            '강의 페이지를 활용해서',
            '편리하게 실습할 수 있습니다.'
        ]
    },
    {
        img: './images/about_2.svg',
        title: '플레이그라운드',
        descs: [
            '강의를 위해 제작한 도구가',
            '반복학습을 도와줍니다.'
        ]
    }
];

 기존 html에서는 div 안에 img, h2등을 이용해서 구성했었다.
 js코드에서는 객체들의 배열로 구성되어 있다.
 보시다시피 복합 데이터임.

 

const $aboutDiv = document.querySelector('.about');

✅ html 문서의 <div class ="about"> 을 선택해 줘야 함.
✅ querySelector로 선택해 주자.

 

for (let i = 0; i < aboutCards.length; i++) {
    const card = aboutCards[i];
    // card 상수 지정. aboutCards 안에 있는 각 객체를 상수로 지정한단 뜻임.
    const $div = document.createElement('div');
    $div.classList.add('about__card');

    const $img = document.createElement('img');
    $img.classList.add('about__icon');
    $img.setAttribute('src', card.img);
    // 속성을 추가할 거기 때문에 setAttribute 사용
    const $h2 = document.createElement('h2');
    $h2.classList.add('about__title')
    $h2.classList.add('_' + (i + 1));
    // html h2태그 아래에
    // html에 쓰였어야 할 원래 클래스 이름, 즉 about__title_순서
    // 와 같이 추가해 준다.
    $h2.textContent = card.title;

    const $p = document.createElement('p');
    // 위아래로 두줄의 텍스트를 써야 함.
    // 전체를 차지하는 div태그를 쓸 거다.
    $p.classList.add('about__text');

    for (const desc of card.descs) {
        const $word = document.createElement('div');
        $word.textContent = desc;
        $p.appendChild($word);
    }
    // 그 뒤 반복문으로 div태그를 하나하나 만들어주고, desc 즉 들어갈 문장을 추가해 준다.
    // 이걸 p태그 아래에 자식으로 추가해주면 된다.
    $div.appendChild($img);
    $div.appendChild($h2);
    $div.appendChild($p);
    // 이제 div에 태그 하나하나 추가해 주고,

    $aboutDiv.appendChild($div);
    // aboutDiv에 div태그를 추가해 준다.
}

✅ 그런 다음, 맨 위에 정의했던 배열 객체 자체를 카드라는 상수로 받고,

✅ 각각 이미지 태그, h2태그, p태그를 만들어 준다.

✅ 특히 p태그는 주석에도 써 있듯이 두 줄이라 div태그를 추가할 건데, aboutDiv>div>p>word(div)>desc라는 구조를 가진다.

 

✅ 아무것도 없었던 about하단 부분이 이렇게 구현이 된다!

 

이제는 진행 바 애니메이션을 구현해 보자.

$currLis = document.querySelectorAll('.curriculum__list > li');

✅ 커리큘럼리스트 안에 있는 li 선택

 

$currProgBar = document.querySelector('.curriculum__progress .bar');

프로그래스 바 선택

 

for (let i = 0; i < $currLis.length; i++) {
    const $li = $currLis[i];
    // 리스트 요소를 $li 로 넣어줌

    $li.addEventListener('mouseenter', () => {
        $currProgBar.style.width = (200 * i) + 'px';
    });
    // 마우스를 올렸을 때
    // 0,200,400,600으로 너비값(px)이 마우스의 움직임에 따라 증가함.
    $li.addEventListener('mouseleave', () => {
        $currProgBar.style.width = 0;
    });
    // 마우스를 뗐을 때
}

반복문을 돌면서, 해당 리스트 요소에 마우스가 닿았을 때, 프로그래스 바의 너비(px)값이 변하고,

마우스를 떼었을 때, 프로그래스바의 너비값이 0이 되는 것이 핵심이다.

 

 구현 성공이다.

 

이제는 문의하기 탭 클릭 시, 슬라이딩 애니메이션이 실행되게끔 구현할 것이다.

 

const $contactTabs = document.querySelectorAll('input[name=contact]');
// querySelectorAll을 사용하여 해당하는 요소를 모두 선택한다.

const $contactSlideCon = document.querySelector('.contact__slide-con');

querySelector 와 querySelectorAll의 큰 차이는 최초로 검색되는 값 한 개 선택이냐 다중선택이냐의 차이다!

 

for (let i = 0; i < $contactTabs.length; i++) {
    const $tab = $contactTabs[i];
    const marginLeft = [0, '-100vw'][i];
    // 슬라이딩했을 때 얼마만큼 이동할건지 정해주는 상수
    // 0,-100vw -> 한 화면 사이즈만큼 왼쪽으로 슬라이딩
    // 왼쪽 탭 선택 시 -> 0
    // 오른쪽 탭 선택 시 -> 왼쪽 탭이 슬라이딩 되고, 오른쪽 탭이 등장해야 하므로 -100vw

    $tab.addEventListener('click', () => {
        $contactSlideCon.style.marginLeft = marginLeft;
    });
    // 클릭 시 슬라이딩하는 이벤트 요소이다.
}

처음엔 코드를 보고 이해가 되지 않았는데, 실제 작동 모습을 상상하면서 선택되는 값에 집중해 보니 이해가 되었다.

위 주석처럼 연락처 보기 탭 클릭시, 왼쪽 탭의 내용이 와야(혹은 돌아와야) 하므로 0만큼 이동해야(돌아와야) 한다.

메시지 남기기 탭 클릭 시, 연락처 보기의 내용이 왼쪽으로 밀리고, 오른쪽 탭의 내용이 와야 하므로 -100vw만큼 이동해야 한다.

 

 구현 성공이다. (사진이라 애니메이션이 안 보입니다...... 구현된거 육안으로 확인했습니다!)

 

 

 

 

이제는 마지막으로 모바일 네비게이션 버튼을 구현해 보고자 한다.

 

const $menuBtn = document.querySelector('.header__menu-btn');

const $headerNav = document.querySelector('.header__nav');
// 네비게이션 부분

 메뉴 버튼 과 네비게이션 부분 각각 선택

 

$menuBtn.addEventListener('click', (e) => {
    $menuBtn.classList.toggle('on');
    $headerNav.classList.toggle('active');

    // 이 요소 아래 레이어에는 클릭 이벤트가 먹히지 않도록
    e.stopPropagation();
});

html코드에는
 클래스 뒤에 on이 붙을 시 버튼의 색상변화
 클래스 뒤에 active가 붙을 시 네비게이션 메뉴가 보이게끔
 설정되어 있다. 똑같이 따라해 주면 된다.
 토글 속성을 이용해서 클래스를 활성/비활성화 해줄 수 있게 한다.
 e.stopPropagation(); 는 네비게이션 메뉴 클릭 후 다른곳을 누르거나, 메뉴를 누를 때 네비게이션 메뉴가 사라지게끔 해 주는 코드다.

 

document
    .querySelector('body')
    .addEventListener('click', () => {
        $menuBtn.classList.remove('on');
        $headerNav.classList.remove('active');
    });

 즉, 다른 곳을 클릭 시, on 과 active클래스를 지워준다. (사라진다)
 e.stopPropagation(); 를 비활성화하면 아무것도 안 열린다.
 왜나하면, body안에 header, section, button등이 들어간다.
 버튼을 누를 때, 그 아래 레이어에 속한 header, body등에 영향이 끼친다.
    이거 이해 못했습니다.. 스터디 때 질문할 예정..

 

 

 구현 성공이다. (모바일 뷰 전용이다.)

 

이로써 2주간 자바스크립트를 공부해 보았다. 뭔가 소감은... 다시 듣는 스터디인 만큼, 클론 코딩이나 프로젝트 등을 해 봐야 잊어버리지 않고, 이해를 더 잘 할 것 같다!

반응형