본문 바로가기

카테고리 없음

[코드잇 스프린트 4주차] 인터랙티브 자바스크립트

✏️ 인터랙티브 자바스크립트 시작하기 

1-01. 웹 서비스와 JavaScript

- JavaScript는 웹 페이지의 여러 요소들을 좀 더 자유롭게 다루기 위해 등장

- HTML : 웹 페이지 구성

- CSS : 웹 페이지 디자인

- JavaScript : 웹 페이지 동작 -> 어떤 버튼을 클릭하면 웹 페이지의 디자인이 바뀐다거나.. 그런 동작

 

1-02. HTML/CSS + JavaScript 맛보기

- HTML과 CSS의 한계 : 한 번 설계한 페이지에 특별히 변화를 주는 것이 어려움

- 일반적으로 <body> 맨 밑에 <script> 추가

<body>
	<script src = "index.js></script>
</body>

- JS를 이용해 실시간으로 HTML에 변화를 주거나 스타일을 수정할 수 있음

 

1-03. id로 태그 선택하기

- 존재하지 않는 태그라면 null값이 return

// id로 HTML 태그 선택
const myTag = document.getElementById('ID_name'); //ID 태그 안에 내용을 전부 포함하게 됨

 

1-05. class로 태그 선택하기

- id를 이용하면 여러 원소를 동시에 선택하기는 어려움 -> class 사용

- Elements인 것에 주의 !

//class로 태그 선택하기
const myTags = document.getElementsByClassName('class_name'); //선택한 class에 속하는 태그들이 배열 형태처럼 return

- return값이 사실 완벽한 배열은 아니다 -> 배열 메소드는 사용할 수 없기 때문

- But, 대괄호표기법으로 인덱스에 접근, length, for of문 사용 가능

- 이런 특성을 가진 애들을 유사배열(Array-Like Object)라고 부른다

- 인덱스는 HTML 코드 작성된 차례대로 정해짐 -> 깊이와는 상관 no

- 원소가 존재하지 않는 class를 선택하면 -> 빈 HTMLCollection이 출력

 

1-06. 유사 배열(Array-Like Object)이란?

- 유사 배열 조건

  • 숫자 형태의 indexing 가능
  • length 프로퍼티 -> index가 있어도 length값이 존재하지 않는다면 그냥 숫자 형태의 key로 구성된 일반 객체
  • 배열의 기본 메소드 사용 불가능
  • Array.isArray('유사배열') 값이 false

- 유사 배열이 이미 만들어진 경우라면 위의 4가지 조건을 만족할 것.

 

1-08. 태그 이름으로 태그 선택하기

const btns = document.getElementsByTagName('button');

- HTML 내에 모든 'button' 태그를 선택

- 여러 요소를 선택할 수 있기 때문에 HTMLCollection으로 결과값 return

- 인자를 '*'로 주면 모든 태그 선택 가능

- 너무 범위가 커서 의도치 않은 실수를 할 수 있기 때문에 자주 사용되지는 않음

 

1-09. css 선택자로 태그 선택하기

// css 선택자로 태그 선택하기
const myTag = document.querySelector('#ID_NAME'); //class 선택할 때는 '.class_name'

- class 이름을 넣게 되면 HTMLCollection 형태로 return되는 게 아니라 가장 첫번째 요소만 선택

- 여러 요소 선택하려 querySelectorAll() 사용 -> NodeList라는 유사 배열이 return값 => 요소가 없을 때 null값 return!!

- getElement~ 메소드보다 querySelector 메소드가 활용도가 더 높다!

 

1-11. 이벤트와 버튼 클릭

- 이벤트 : 웹 페이지에서 일어날 수 있는 대부분의 일 (ex. 마우스 움직이기, 마우스 클릭, 페이지 스크롤 등)

- 이벤트 핸들링 : 자바스크립트를 통해 이벤트를 다루는 일

- 이벤트 핸들러 : 이벤트가 발생했을 때 동작하는 코드

// 이벤트와 버튼 클릭
const btn = document.querySelector('#myBtn');

// 이벤트 핸들링(Event Handling)
btn.onclick = function (){ // 이벤트 핸들러(리스너)
	console.log('function call!');
}

- 이벤트 핸들링 코드를 HTML 파일에 직접 작성할 수도 있지만 권장 x

 

1-12. [실습] 정답일까?

- 버튼을 클릭하면 경고창이 뜨는 코드

const btn = document.querySelector('#grade');

btn.onclick = function(){
  alert('정답입니다!👏🏻');
}

✏️ 브라우저와 자바스크립트 

2-01. 브라우저도 객체다?

- window : 브라우저 자체를 가리키는 객체 -> 자바스크립트에서 최상단에 존재하는 객체(자바스크립트의 모든 객체를 포함하고 있다는 뜻)

- 원래라면 window.console.log() 이런 식이지만 모든 객체가 window에 속하기 때문에 안붙여도 됨

// window : 전역객체 (Global Object)
console.log(window);
console.log(window.innerWidth);
console.log(window.innerHeight);

 

2-02. DOM

- DOM(Document Object Model) : 문서 객체 모델 -> 웹 페이지에 나타나는 HTML 문서 전체를 객체로 표현한 것

- document 객체를 사용하면 -> 웹 페이지 내부의 무엇이든 수정 / 추가 가능

console.log(document); // HTML 문서 자체가 출력(태그 형태)
console.dir(document); // 객체 형태로 다양한 프로퍼티들이 출력

 

2-03. console.dir?

- console.log()console.dir() 모두 입력받은 값을 콘솔에 출력하는 역할

- dir 메소드는 무조건 문자열로 출력

- log는 값 자체를, dir은 객체의 속성을 출력 ⭐

- log는 파라미터로 여러 개 가능, dir은 하나만 가능

- log는 DOM 객체를 HTML 형태로 출력, dir은 객체 형태로 출력 ⭐⭐⭐

 

2-04. DOM 트리

출처 : 코드잇

[ 위치 관계 ]

- 부모/자식 노드 : 상하 관계에 있는 노드들 

- 형제 노드(Sibling node) : 같은 위치 상에 있는 노드들

 

[ 내용 ]

- 요소 노드(Element node) : 태그를 담고 있는 노드 (html, head, body 등)

- 텍스트 노드(Text node) : 문자열을 표현하는 노드 (그림 상에서 회색 노드) -> 자식 노드를 가질 수 없기 때문에 leaf node

- 일반적으로 텍스트 노드는 요소 노드의 자식 노드

- 이 밖에도 코멘트 노드, 문서 노드 등이 있지만 잘 사용되지는 않는다.

 

2-05. DOM 트리 여행하기

- DOM 트리의 관계 이용해서 요소 선택하기

const myTag = document.querySelector('#content');

//자식 요소 노드
console.log(myTag.children); //myTag의 모든 child 요소들이 HTMLCollection으로 출력됨
console.log(myTag.childtren[1]);
console.log(myTag.firstElementChild);
console.log(myTag.lastElementChild);

//부모 요소 노드
console.log(myTag.parentElement);

//형제 요소 노드
console.log(myTag.previousElementSibling);
console.log(myTag.nextElementSibling);

 

2-06. DOM 트리 여행하기 : 부록

- 요소 노드 이외에 모든 노드에 적용되는 프로퍼티

node.childNodes //node의 자식 노드 모음(NodeList)
node.firstChild //node의 첫 번째 자식 노드
node.lastChild //node의 마지막 자식 노드
node.parentNode // node의 부모 노드 하나
node.previousSibling //node의 prev/left에 있는 노드 하나
node.nextSibling //node의 next/right에 있는 노드 하나

 

2-08. 요소 노드 프로퍼티

//요소 노드 주요 프로퍼티
const myTag = document.querySelector('#list-1');

//innerHTML : 요소 안에 HTML을 수정할 때 활용
console.log(myTag.innerHTML); //요소 안에 있는 HTML 자체를 문자열로 return
myTag.innerHTML += '<li>new</li>';

//outerHTML : 요소 자체를 가리키기 때문에 요소 자체가 수정됨
console.log(myTag.outerHTML); //요소를 포함한 HTML 자체를 문자열로 return
myTag.innerHTML = '<li>new</li>'; //이런 식으로 하면 #list-1 요소가 아예 바껴버리는 것 ,,

//textContent : 특수문자도 전부 텍스트로 처리하는 것 주의!
console.log(myTag.textContent); //요소 안에 있는 내용 중 HTML 제외한 텍스트만 return
myTag.textContent = '<li>new text!</li>'; //이렇게 하면 태그로 인식하는 게 아니라 모두 텍스트로 인식함

 

2-11. 요소 노드 추가하기

- 요소 노드를 직접 생성해서 추가하는 방법

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

//1. 요소 노드 만들기 : document.createElement('태그이름');
const first = document.createElement('li');

//2. 요소 노드 꾸미기 : textContent, innerHTML ...
first.textContent = '처음';

//3. 요소 노드 추가하기 : NODE.prepend, append, after, before
tommorow.prepend(first); //tommorow 요소 가장 첫번째 자식 요소로 추가
tommorow.append(first); //tommorow 요소 가장 마지막 자식 요소로 추가
tommorow.before('문자열', first); //tommorow 요소 이전 요소(앞쪽)로 추가
tommorow.after(first); //tommorow 요소 다음 요소(뒤쪽)로 추가

 

2-12. 노드 삭제와 이동하기

//노드 삭제하기 : Node.remove();
tomorrow.remove(); //tomorrow 노드가 삭제됨
today.children[2].remove();

//노드 이동하기 : prepend, append, before, after
today.append(tomorrow.children[1]); //today의 맨 앞으로 tomorrow의 자식 요소 1번을 이동
tomorrow.children[1].after(today.children[1]);

 

2-14. HTML 속성 다루기

- 속성 접근하기

//elem.getAttribute('속성'): 속성에 접근하기 -> 비표준 속성에도 접근 가능
console.log(tomorrow.getAttribute('href'));

//여기서부터는 표준 속성에만 접근 가능
//id 속성
console.log(tomorrow.id);

//class 속성
console.log(item.className);

//href 속성
console.log(link.href);

- 속성 추가하기

// elem.setAttribute('속성', '값'): 속성 추가(수정)하기
tomorrow.setAttribute('class', 'list'); //추가
link.setAttribute('href', 'naver.com'); //수정

- 속성 삭제하기

//elem.removeAttribute('속성') : 속성 제거하기
tomorrow.removeAttribute('class');

 

2-16. 스타일 다루기

//style 프로퍼티
today.children[0].style.textDecoration = 'line-through';

- style 프로퍼티를 이용하면 값이 HTML 코드에 직접 style 속성으로 추가됨 -> 오류  발생할 가능성 있음!

- 미리 class를 만들어두고, 그 class를 추가하는 식으로 스타일 적용시킴

//elem.className -> 아예 클래스 자체를 바꿔버린다!
today.children[1].className = 'done'; //미리 작성해둔 done 클래스의 css 스타일이 적용됨

//elem.classList: add, remove, togggle
tomorrow.children[1].classList.add('done', 'other'); //기존 클래스에 done, other 클래스 추가
tomorrow.children[1].classList.remove('done'); //done 클래스 삭제
tomorrow.children[1].classList.toggle('done'); //없으면 추가, 있으면 삭제
tomorrow.children[1].classList.toggle('done', true); //true면 추가만, false면 삭제만! -> 자주사용NO

 

2-18. 비표준 속성 다루기

[status] { /* status 속성을 가진 태그들 선택 */
  padding: 5px 10px;
}

[status="대기중"] { /* status 속성값이 '대기중'인 태그들을 선택 */
  background-color: #FF6767;
  color: #FFFFFF;
}

- 비표준 속성 활용하기

  • 선택자로 활용
const fields = document.querySelectorAll('[field]');
  • 값을 표시할 태그를 구분할 때 활용
  • 스타일이나 데이터 변경에 활용

 

- 비표준 속성을 사용하는 것은 안전하지 않을 수 있다 -> 그 속성이 나중에 표준으로 등록될 수도 있기 때문!

=> data-'비표준 속성'으로 값을 설정해주고 속성값을 가져올때는 element.dataset.비표준속성 으로 접근!


✏️ 이벤트 살펴보기 

3-01. 이벤트 핸들러 등록하기

- 하나의 요소에 여러 개의 독립적인 이벤트를 추가할 때

function event1() {
	console.log('Hi Codeit!');
}
function event2() {
	console.log('Hi again!');
}

// elem.addEventListener(event, handler) : 이벤트 핸들러 등록
btn.addEventListener('click', event1);
btn.addEventListener('click', event2);

// elem.removeEventListener(event, handler) : addEventListner로 등록한 이벤트 핸들러 삭제
btn.removeEventListener('click', event2); //반드시 이벤트 등록할 때 쓴 함수의 이름으로!!

 

3-02. 다양한 이벤트 ⭐⭐

- 마우스 이벤트

  • mousedown : 마우스 버튼을 누르는 순간
  • mouseup : 마우스 버튼 눌렀다 떼는 순간
  • click : 마우스 왼쪽 버튼 클릭
  • dbclick : 마우스 왼쪽 버튼 더블 클릭
  • contextmenu : 마우스 오른쪽 버튼 클릭
  • mousemove : 마우스를 움직이는 순간
  • mouseover : 마우스 포인터가 요소 위로 올라왔을 때
  • mouseout : 요소에서 벗어났을 때
  • mouseenter : 마우스 포인터가 요소 위로 올라왔을 때 (버블링 x)
  • mouseleave : 요소에서 벗어났을 때 (버블링x)

 

- 키보드 이벤트

  • keydown : 키보드 버튼 누르는 순간
  • keypress : 출력가능한 키보드 버튼 (ex. shift, esc 등에서는 작동 x)
  • keyup : 버튼 눌렀다 떼는 순간

 

- 포커스 이벤트

  • focusin : 요소에 포커스 되는 순간
  • focusout : 요소로부터 포커스 빠져나간 순간
  • focus : 요소에 포커스 되는 순간 (버블링 x)
  • blur : 요소로부터 포커스 빠져나간 순간 (버블링 x)

 

- 입력 이벤트

  • change : 입력된 값이 바뀔 때
  • input : 값이 입력될 때
  • select : 입력 양식의 하나가 선택될 때
  • submit : 폼을 전송할 때

 

- 스크롤 이벤트

  • scroll : 스크롤 바 움직일 때

 

- 윈도우 창 이벤트

  • resize : 윈도우 사이즈를 움직일 때 발생

 

3-04. 이벤트 객체

// 이벤트 객체 (Event Object)
const myInput = document.querySelector('#myInput');
const myBtn = document.querySelector('#myBtn');

function printEvent(event) { //이벤트 핸들러의 첫번째 파라미터는 무조건 이벤트 객체가 전달!
  console.log(event);
  event.target.style.color = 'red';
}

myInput.addEventListener('keydown', printEvent);
myBtn.addEventListener('click', printEvent);

 

3-05. 이벤트 객체 프로퍼티

- 공통 프로퍼티

  • type : 발생한 이벤트의 type (이벤트 이름)
  • target : 이벤트가 발생한 해당 dom 요소
  • currentTarget : 이벤트 핸들러가 등록된 요소
  • timeStamp : 이벤트 발생 시각 (페이지 로드된 시각부터 밀리초로 계산된 값)
  • bubbles : 버블링 단계인지 판단하는 값

 

- 마우스 이벤트

- 키보드 이벤트

 

3-06. [실습] 완료한 일 체크하기!

- JS

더보기
const toDoList = document.querySelector('#to-do-list');
const items = toDoList.children;

// 1. updateToDo 함수를 완성해 주세요
function updateToDo(event) {
  event.target.classList.toggle('done');
}

// 2. 반복문을 활용해서 각 li태그에 이벤트 핸들러를 등록해 주세요
for (item of items){
  item.addEventListener('click', updateToDo);
}


// 테스트 코드
items[2].removeEventListener('click', updateToDo);

 

3-07. 이벤트 버블링

- 이벤트 버블링 : 부모 요소의 이벤트 핸들러가 같이 동작하는 것(윈도우 객체까지 모두 타고 올라가며 작동된다)

- 버블링된다고 이벤트 target까지 부모 요소로 변하는 것은 아님! -> target은 처음 이벤트가 발생한 시작점 그대로

- currentTarget : 실제로 이벤트가 발생중인 target (자주 사용x)

- 버블링 막는 법 -> 권장 x, 버블링에 대해 잘 알고 설계하면 버블링 막을 일이 별로 없을 것

for (let item of items) {
  item.addEventListener('click', function(e) {
    console.log('item Event');
    console.log(e.currentTarget);
	e.stopPropagation(); //버블링을 막는다
  });
}

 

3-08. 캡쳐링

- 표준 DOM 이벤트에서 정의한 이벤트 흐름

  1. 캡쳐링 단계 : 이벤트가 하위 요소로 전파되는 단계
  2. 타깃 단계 : 이벤트가 실제 타깃 요소에 전달되는 관계 -> 가장 처음 이벤트 핸들러가 동작하는 순간
  3. 버블링 단계 : 이벤트가 상위 요소로 전파되는 단계

 

- 캡처링 단계에서 이벤트 핸들러 동작시키는 법 : addEventListener()의  세번째 프로퍼티에 true

 

3-10. 이벤트 위임

- 각 아이템마다 이벤트 핸들러를 달아주면 새로운 아이템을 추가할 때마다 새로 등록해 줘야한다는 문제가 있음

- 이벤트 위임 : 자식 요소에서 발생하는 이벤트를 부모 요소에서 한번에 관리하 방식 -> 버블링 이용

// 이벤트 위임 (Event Delegation)
const list = document.querySelector('#list');
list.addEventListener('click', function(e) {
	// if (e.target.tagName === 'LI')
	if (e.target.classList.contains('item')) { //item이 해당 요소의 class 속성에 있는지 확인
		e.target.classList.toggle('done');
	}
});

const li = document.createElement('li');
li.classList.add('item');
li.textContent = '일기 쓰기';
list.append(li);

- 자식 요소에는 아무런 이벤트가 등록되지 않았으니 이벤트 발생 x -> 부모 요소의 이벤트 실행 (이런 원리를 이용한 것)

 

3-12. 브라우저의 기본 동작

// 브라우저의 기본 동작
const link = document.querySelector('#link');
const checkbox = document.querySelector('#checkbox');
const input = document.querySelector('#input');
const text = document.querySelector('#text');

//event.preventDefault : 브라우저 기본 동작 막기
link.addEventListener('click', function(e) {
	e.preventDefault();
	alert('지금은 이동할 수 없습니다.');
});

input.addEventListener('keydown', function(e) {
	if (!checkbox.checked) {
		e.preventDefault();
		alert('체크박스를 먼저 체크해 주세요.');
	}
});

document.addEventListener('contextmenu', function(e) {
	e.preventDefault();
	alert('마우스 오른쪽 클릭은 사용할 수 없습니다.');
});

✏️ 다양한 이벤트 알아보기 

4-01. 마우스 버튼 이벤트

- 더블 클릭 이벤트 주의할 점 : 클릭 이벤트가 2번 일어난 후에 더블클릭 이벤트가 발생

/** 
 * [마우스 버튼 이벤트]
 * 
 * > MouseEvent.button
 * 0: 마우스 왼쪽 버튼
 * 1: 마우스 휠
 * 2: 마우스 오른쪽 버튼
 * 
 * > MouseEvent.type
 * click: 마우스 왼쪽 버튼을 눌렀을 때
 * contextmenu: 마우스 오른쪽 버튼을 눌렀을 때
 * dblclick: 동일한 위치에서 빠르게 두번 click할 때
 * mousedown: 마우스 버튼을 누른 순간
 * mouseup: 마우스 버튼을 눌렀다 뗀 순간
 */

 

4-03. 마우스 이동 이벤트 I

/** 
 * [마우스 이동 이벤트]
 * 
 * > MouseEvent.type
 * mousemove: 마우스 포인터가 이동할 때
 * mouseover: 마우스 포인터가 요소 밖에서 안으로 이동할 때
 * mouseout: 마우스 포인터가 요소 안에서 밖으로 이동할 때 
 *
 * > MouseEvent.clientX, clientY
 * : 화면에 표시되는 >창 기준< 마우스 포인터 위치   
 * 
 * > MouseEvent.pageX, pageY
 * : 웹 문서 >전체 기준< 마우스 포인터 위치
 * 
 * > MouseEvent.offsetX, offsetY
 * : 이벤트가 발생한 >요소 기준< 마우스 포인터 위치
 */
 
const box1 = document.querySelector('#box1');

function onMouseMove(e) {
  console.log(`client: (${e.clientX}, ${e.clientY})`);
  console.log(`page: (${e.pageX}, ${e.pageY})`);
  console.log(`offset: (${e.offsetX}, ${e.offsetY})`);
  console.log('------------------------------------');
}

box1.addEventListener('mousemove', onMouseMove);

 

4-05. 마우스 이동 이벤트 II

/** 
 * [마우스 이동 이벤트]
 * 
 * > MouseEvent.type
 * mousemove: 마우스 포인터가 움직일 때
 * mouseover: 마우스 포인터가 요소 밖에서 안으로 움직일 때
 * mouseout: 마우스 포인터가 요소 안에서 밖으로 움직일 때 
 * 
 * > MouseEvent.target
 * : 이벤트가 발생한 요소
 * 
 * > MouseEvent.relatedTarget
 * : 이벤트가 발생하기 직전(또는 직후)에 마우스가 위치해 있던 요소
 */

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

function printEventData(e) {
  console.log('event:', e.type);
  console.log('target:', e.target);
  console.log('relatedTarget:', e.relatedTarget);
  console.log('------------------------------------');
  if (e.target.classList.contains('cell')) {
    e.target.classList.toggle('on');
  }
}

box2.addEventListener('mouseover', printEventData);
box2.addEventListener('mouseout', printEventData);

- mouseover : relatedTarget -> target (마우스 들어옴)

- mouseout : target -> relatedTarget (마우스 나감)

- 2개의 이벤트는 항상 동시에 발생한다.

 

4-06. mouseenter / mouseleave

- 버블링이 일어나지 않는다. (mouseover/mouseout은 일어남)

- 자식 요소의 영역을 계산하지 않는다.

- 이벤트가 자식 요소에 영향을 끼치는지가 가장 큰 차이!

 

4-08. 키보드 이벤트

/** 
 * [키보드 이벤트]
 * 
 * > KeyboardEvent.type
 * keydown: 키보드 버튼을 누른 순간
 * keypress: 키보드 버튼을 누른 순간
 * keyup: 키보드 버튼을 눌렀다 뗀 순간
 * 
 * > KeyboardEvent.key
 * : 이벤트가 발생한 버튼의 값
 * 
 * > KeyboardEvent.code
 * : 이벤트가 발생한 버튼의 키보드에서 물리적인 위치
 */

- keypress 이벤트는 하나의 키를 계속 누르고 있어도 1번만 발생하지만, keydown은 계속 이벤트 발생

- keypress 이벤트는 출력이 가능한 키를 누를 때만 발생 -> 출력이 가능하더라도 영어가 아닐 때는 반응 x

- keypress는 별로 권장 x

 

4-09. [실습] 똑Talk한 Enter키!

더보기
const chatBox = document.querySelector('#chat-box');
const input = document.querySelector('#input');
const send = document.querySelector('#send');

function sendMyText() {
  const newMessage = input.value;
  if (newMessage) {
    const div = document.createElement('div');
    div.classList.add('bubble', 'my-bubble');
    div.innerText = newMessage;
    chatBox.append(div);
  } else {
    alert('메시지를 입력하세요...');
  }

  input.value = '';
}

send.addEventListener('click', sendMyText);

// 여기에 코드를 작성하세요
function checkEnter(event){
  if(event.key == 'Enter' && !event.shiftKey){
    event.preventDefault(); //기본 동작(줄바꿈) 금지 -> 초기화
    sendMyText();
  }
  
}
input.addEventListener('keypress', checkEnter);

 

4-10. input 태그 다루기

- change : 입력이 끝났다는 암시를 줘야 이벤트 발생 -> 엔터키를 누르거나 focusout이 되면 같이 발생!

/**
 * [input 태그 다루기]
 *  
 * > 포커스 이벤트
 * focusin: 요소에 포커스가 되었을 때
 * focusout: 요소에 포커스가 빠져나갈 때
 * focus: 요소에 포커스가 되었을 때 (버블링 x)
 * blur: 요소에 포커스가 빠져나갈 때 (버블링 x)
 * 
 * > 입력 이벤트
 * input: 사용자가 입력을 할 때
 * change: 요소의 값이 변했을 때
 */

const el = document.querySelector('#form');

function printEventType(e) {
  console.log('type:', e.type);
  console.log('target:', e.target);
  console.log('---------');
}

el.addEventListener('focusin', printEventType);
el.addEventListener('focusout', printEventType);
el.addEventListener('input', printEventType);
el.addEventListener('change', printEventType);

 

4-12. 스크롤 이벤트

// Scroll 이벤트
let lastScrollY = 0;

function onSroll() {
  const nav = document.querySelector('#nav');
  const toTop = document.querySelector('#to-top');
  const STANDARD = 30;
  
  if (window.scrollY > STANDARD) { // 스크롤이 30px을 넘었을 때
    nav.classList.add('shadow');
    toTop.classList.add('show');
  } else { // 스크롤이 30px을 넘지 않을 때
    nav.classList.remove('shadow');
    toTop.classList.remove('show');
  } 

	if (window.scrollY > lastScrollY) { // 스크롤 방향이 아랫쪽 일 때
    nav.classList.add('lift-up');
  } else { // 스크롤 방향이 윗쪽 일 때
    nav.classList.remove('lift-up');
  }

  lastScrollY = window.scrollY;
}

window.addEventListener('scroll', onSroll);

23/09/26

이벤트는 진짜 해도해도 넘 어렵다 ,, 어떻게 해야 익숙해질 수 있는거지ㅠ