JavaScript

LEE GYUHO·2023년 9월 24일
0

인터랙티브 JavaScript

  • id로 태그 선택

    • const 변수명 = document.getElementById('id명');

    • HTML 문서에 준재하지 않는 id값으로 태그를 선택하면 null이 나온다.

  • class로 태그 선택

    • const 변수명 = document.getElementsByClassName('class명');

    • 태그의 순서는 깊이와 관계없이 위에서부터 차례대로이다.

    • 변수명[1](숫자 형태의 indexing), 변수명.length, for..of문이 사용 가능하다.
      배열의 형태와 유사하지만 배열의 메소드는 사용이 불가능하다.
      이런 것들을 유사배열(Array-Like Object)이라고 한다.

    • HTML 문서에 준재하지 않는 class값으로 태그를 선택하면 HTMLCollection[]이렇게 빈 HTMLCollecion이 출력된다. length는 0이고 null과 다른 값이다.

    • 클래스가 하나밖에 없는 값에 접근하려고 했을때
      document.getElementsByClassName('class명');
      이렇게 하면 태그가 하나밖에 없으니 그 태그가 바로 선택될 것이라고 생각할 수 있지만 아니다. 요소 한가지가 들어있는 HTMLCollection이 출력된다. 따라서 그 태그를 선택하려면 변수명[0]을 해야한다.

  • 태그 이름으로 선택

    • document.getElementsByTagName('태그이름');
  • css 선택자로 태그 선택

    • const myTag = document.querySelector('#myNumber');
      const myTag2 = document.getElementsById('myNumber');
      이 두개는 같은 결과를 출력한다.

    • const myTag = document.querySelector('.color-btn');
      이것은 color-btn을 클래스로 가지고 있는 첫번째 요소만을 출력한다.

    • const myTags = document.querySelectorAll('.color-btn');
      이렇게 해야 모든 요소를 출력한다.
      NodeList라는 유사배열을 출력한다.

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

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

브라우저와 JavaScript

  • window (전역객체 Global Object)
    console.log(window); //윈도우의 내장 객체들이 나온다

  • DOM (Document Object Model / 문서 객체 모델)
    console.log(document); //html태그가 출력된다(값에 중점)
    console.log(typeof document); // object
    console.dir(document); // 객체 형태로 다양한 프로퍼티들이 출력된다(객체의 속성에 중점)

  • DOM 트리

    • 각각의 태그들을 노드라고 부르며 부모노드, 자식노드, 형제노드 관계에 있다.

    • Node Type으로는 요소 노드(Element Node)와 텍스트 노드(Text Node) 가있다. 텍스트 노드는 요소 노드의 자식 노드이며 자식 노드를 가질 수 없다. 그리고 리프 노드(Leaf Node)라고도 불린다.

  • DOM 트리 접근 (요소 노드)

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

      console.log(myTag)

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

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

      //자식 요소 노드
      console.log(myTag.children[1]);
      console.log(myTag.firstElementChild);
      console.log(myTag.lastElementChild);

    • myTag.parentElement.nextElementSibling);
      이런 식으로 접근도 가능하다.

  • 요소 노드 프로퍼티

    • innerHTML(줄바꿈, 들여쓰기 모두 포함된다, 요소 노드 내부의 HTML 코드를 문자열로 리턴해 준다.)
      console.log(myTag.innerHTML);

      myTag.innerHTML = '< li>Exotic< /li>';
      이렇게 하면 기존 값이 수정된다.(기존 값이 완전히 새로운 값으로 교체)

      myTag.innerHTML += '< li>Exotic< /li>';
      이렇게 하면 기존의 것에서 추가도 가능하다.

    • outerHTML(줄바꿈, 들여쓰기 모두 포함된다, 해당 요소를 포함한 전체 HTML코드를 문자열로 리턴해준다)
      console.log(myTag.outerHTML);

      myTag.outerHTML = '< ul id="new-list">< li>Exotic< /li>< /ul>'
      outerHTML은 해당요소 전체를 가리키는 특성 때문에 요소 자체가 새로운 요소로 교체되는 결과를 얻게된다.(수정 x)

    • textContent(줄바꿈, 들여쓰기 모두 포함된다, 요소 안에 있는 내용들 중에서 HTML을 제외한 text만 가져온다)
      console.log(myTag.textContent);

      myTag.textContent = 'new text!';
      innerHTML과 마찬가지로 수정한다.(기존 값이 완전히 새로운 값으로 교체)

      특수문자도 text로 처리하기 때문에 HTML코드처럼 작성해도 그대로 text로 나온다

  • 요소 노드 추가
    const tomorrow = document.querySelector('#tomorrow');

      1. 요소 노드 만들기: document.createElement('태그이름')
        const first = document.createElement('li');
      1. 요소 노드 꾸미기: textContent, innerHTML, ...
        first.textContent = '처음';
      1. 요소 노드 추가하기: NODE.prepend, append, after, before
        tomorrow.prepend(first);

        const last = document.createElement('li');
        last.textContent = '마지막';
        tomorrow.append(last);

        const prev = document.createElement('p');
        prev.textContent = '이전';
        tomorrow.before(prev); // tomorrow.before('문자열'); 이런식으로도 가능

        const next = document.createElement('p');
        next.textContent = '다음';
        tomorrow.append(next);

    여러개 전달이 가능하다
    ex)tomorrow.befor('문자열', prev);
    입력 순서대로 문자열이 위에 그 다음에 prev가 출력된다

  • 노드 삭제와 이동
    const today = document.querySelector('#today');
    const tomorrow = document.querySelector('#tomorrow');

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

    • 노드 이동하기: prepend,append, before, after
      today.append(tomorrow.children[1]);
      tomorrow.children[1].after(today.children[1]);
      tomorrow.children[2].before(today.children[1]);
      tomorrow.lastElementChild.before(today.children[1]);

  • HTML 속성 다루기
    const tomorrow = document.querySelector('#tomorrow');
    const item = tomorrow.firstElementChild;
    const link = item.firstElementChild;

    • elem.getAttribute('속성'): 속성에 접근하기
      console.log(tomorrow.getAttribute('href'));
      console.log(item.getAttribute('class'));
    • elem.setAttribute('속성', '값'): 속성 추가(수정)하기
      tomorrow.setAttribute('class', 'list'); //추가
      link.setAttribute('href', 'https://www.codeit.kr'); //추가
    • elem.removeAttribute('속성'): 속성 제거하기
      tomorrow.removeAttribute('href');
      tomorrow.removeAttribute('class');
  • 스타일 다루기

    • style 프로퍼티
      today.children[0].style.textDecoration = 'line-through';
      today.children[0].style.backgroundColor = '#DDDDDD';
      (text-decoration -> textDecration 이렇게 카멜을 사용해야 한다)

    • elem.className
      today.children[1].className = 'done';
      (style.css에 있는 done이라는 클래스를 적용시키는 것)

    • elem.classList: add, remove, toggle(없으면 추가 있으면 삭제)
      (class의 속성값을 유사배열로 다루는 프로퍼티)
      today.classList;
      today.children[1].classList;

      const item = tomorrow.children[1];
      item.classList.add('done'); (item.classList.add('done', 'other');)이렇게 여러 파라미터 전달 가능
      item.classList.remove('done'); (remove도 여러개 파라미터 전달이 가능하다)
      item.classList.toggle('done');

이벤트

  • 이벤트 핸들러 등록
let btn = document.querySelector('#myBtn');

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

function event2() {
  console.log('Hi again!');
}
  • elem.addEventListener(event, handler)
    btn.addEventListener('click', event1())
    //이렇게 event1()를 하게 되면 event1 함수의 리턴값이라는 표현이기 때문에 빼야한다
    btn.addEventListener('click', event2)

  • elem.removeEventListener(event, handler)
    btn.removeEventListener('click', event2)
    (removeEventListener 메소드는 파라미터로 전달하는 타입과 이벤트 핸들러가 addEventListener 메소드로 등록할 때와 동일 할 때만 이벤트 핸들러를 삭제할 수 있다.)

  • 이벤트

    • 마우스 이벤트 (MouseEvent.type) / 각 이벤트의 순서가 있다
      mousedown 마우스 버튼을 누르는 순간
      mouseup 마우스 버튼을 눌렀다 떼는 순간
      click 왼쪽 버튼을 클릭한 순간
      dblclick 왼쪽 버튼을 빠르게 두 번 클릭한 순간
      contextmenu 오른쪽 버튼을 클릭한 순간
      mousemove 마우스를 움직이는 순간
      mouseover 마우스 포인터가 요소 위로 올라온 순간
      mouseout 마우스 포인터가 요소에서 벗어나는 순간
      mouseenter 마우스 포인터가 요소 위로 올라온 순간 (버블링이 일어나지 않음)
      mouseleave 마우스 포인터가 요소에서 벗어나는 순간 (버블링이 일어나지 않음)

    • 키보드 이벤트
      keydown 키보드의 버튼을 누르는 순간
      keypress 키보드의 버튼을 누르는 순간 ('a', '5' 등 출력이 가능한 키에서만 동작하며, Shift, Esc 등의 키에는 반응하지 않음)
      keyup 키보드의 버튼을 눌렀다 떼는 순간

    • 포커스 이벤트
      focusin 요소에 포커스가 되는 순간
      focusout 요소로부터 포커스가 빠져나가는 순간
      focus 요소에 포커스가 되는 순간 (버블링이 일어나지 않음)
      blur 요소로부터 포커스가 빠져나가는 순간 (버블링이 일어나지 않음)

    • 입력 이벤트
      change 입력된 값이 바뀌는 순간
      input 값이 입력되는 순간
      select 입력 양식의 하나가 선택되는 순간
      submit 폼을 전송하는 순간

    • 스크롤 이벤트
      scroll 스크롤 바가 움직일 때

    • 윈도우 창 이벤트
      resize 윈도우 사이즈를 움직일 때 발생

  • 이벤트 객체(이벤트 핸들러가 되는 함수의 첫 파라미터는 자동으로 이벤트 객체가 전달된다.)

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

function printEvent(envnt) { //(event)대신 (e)로 쓰기도 한다
  console.log(event);
}

myInput.addEventListener('keydown', printEvent);
myBtn.addEventListener('click', printEvent);
  • 이벤트 버블링
    • 한 요소에 이벤트가 발생하면, 이 요소에 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 동작합니다. 가장 최상단의 조상 요소를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작합니다.
const content = document.querySelector('#content');
const title = document.querySelector('#title');
const list = document.querySelector('#list');
const items = document.querySelector('.item');

content.addEventListener('click', function(e) {
  console.log('content Event');
  console.log(e.target);
});

for(let item of items) {
  item.addEventListener('click', function(e){
    console.log('item Event');
    console.log(e.target);
  });
}
  • target은 각 이벤트 핸들러가 동작할 때 해당 핸들러가 등록된 요소가 타겟이 될 것이라고 오해하는 경우가 있는데 이것은 아니다. 타겟은 변하지 않는 것을 확인할 수 있다.
    이벤트 버블링이 일어나도 이벤트 객체의 타겟 프로퍼티는 변하지 않고 처음 이벤트가 발생한 시작점을 담고 있다.

  • 이벤트 핸들러가 등록된 요소에 접근하고 싶은 경우에는 e.currentTarget을 사용하면 된다. 그러면 이벤트 핸들러가 동작하는 요소가 출력된다.

  • 버블링을 멈추려면 이벤트 객체에 e.stopPropagation();을 사용하면 된다.
    꼭 필요한 경우가 아니라면 사용을 피하는 것이 좋다

  • 이벤트 흐름 3가지

    • 캡처링 단계: 이벤트가 하위 요소로 전파되는 단계 (이벤트 객체의 target 프로퍼티가 되는 요소에 등록되어있던 이벤트 핸들러가 동작하는 단계인데, 쉽게 생각해서 가장 처음 이벤트 핸들러가 동작하게 되는 순간이라고 생각하시면 됩니다.)

    • 타깃 단계: 이벤트가 실제 타깃 요소에 전달되는 단계 (이벤트 객체의 target 프로퍼티가 되는 요소에 등록되어있던 이벤트 핸들러가 동작하는 단계인데, 쉽게 생각해서 가장 처음 이벤트 핸들러가 동작하게 되는 순간이라고 생각하시면 됩니다.)

    • 버블링 단계: 이벤트가 상위 요소로 전파되는 단계

  • 이벤트 위임 (Event Delegation)

const List = document.quertySelelctor('#list');

for(let item of list.children){
	item.addEventListener('click', function(e){
	e.target.classList.toggle('done');
	});
}

이렇게 할 경우 새로운 것을 추가했을 때 거기에는 이벤트가 적용되지 않는다.

list.addEventListener('click', function(e){
	e.target.classList.toggle('done');
});

이렇게 부모에게 이벤트를 주게 되면 새로운 것을 추가했을 때에도 적용된다.
그치만 이렇게 하면 자식요소들이 아닌 부모를 클릭해도 이벤트가 적용된다.
따라서 아래처럼 작성해 줘야 한다.

list.addEventListener('click', function(e){
//if(e.target.tagName === 'LI')
	if(e.target.classList.contains('item')){
	e.target.classList.toggle('done');
});
  • 브라우저 기본 동작
    const link = document.querySelecor('#link');
    const checkbox = document.querySelecor('#checkbox');
    const input = document.querySelecor('#input');
    const text = document.querySelecor('#text');

    event.preventDefault(이 기능도 꼭 필요한 경우에만 사용해야 한다.)

    link.addEventListener('click', function(e){
    	e.preventDefault();
    	alert('지금은 이동할 수 없습니다.');
    });
    
    input.addEventListener('keydown', function(e){
    	if(!checkbox.checked){
    		e.preventDefault();
    		alert('체크박스를 먼저 클릭해 주세요.');
    	 }
    });
    
    text.addEventListener('contextmenu', function(e){
    	e.preventDefault();
    	alert('마우스 오른쪽 클릭은 사용할 수 없습니다.');
    });

다양한 이벤트

  • 마우스 이벤트 (MouseEvent.type) / 각 이벤트의 순서가 있다
    mousedown 마우스 버튼을 누르는 순간
    mouseup 마우스 버튼을 눌렀다 떼는 순간
    click 왼쪽 버튼을 클릭한 순간
    dblclick 왼쪽 버튼을 빠르게 두 번 클릭한 순간
    contextmenu 오른쪽 버튼을 클릭한 순간
    mousemove 마우스를 움직이는 순간
    mouseover 마우스 포인터가 요소 위로 올라온 순간
    mouseout 마우스 포인터가 요소에서 벗어나는 순간
    mouseenter 마우스 포인터가 요소 위로 올라온 순간 (버블링이 일어나지 않음)
    mouseleave 마우스 포인터가 요소에서 벗어나는 순간 (버블링이 일어나지 않음)

    • MouseEvent.clientX, clientY: 화면에 표시되는 창 기준 마우스 포인터 위치
    • MouseEvent.pageX, pageY: 웹 문서 전체 기준 마우스 포인터 위치
    • MouseEvent.offsetX, offsetY: 이벤트가 발생한 요소 기준 마우스 포인터 위치

mousemove

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})`);
}

box1.addEventListener('mousemove', onMouseMove);

mouseover, mouseout

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

function printEventData(e){
	if(e.target.classList.contains('cell')){
		e.target.classList.toggle('on');
	}
}

box2.addEventListener('mouseover', printEventData);
box2.addEventListener('mouseout', printEventData);
  • 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);
    }
    
    box2.addEventListener('mouseover', printEventData);
    box2.addEventListener('mouseout', printEventData);

    이렇게 하면 마우스 위치가 어디에서 어디로 옮겨졌는지 알 수 있다.

  • 키보드 이벤트

    • keydown: 키보드 버튼을 누른 순간

    • keypress: 키보드 버튼을 누른 순간(권장하지 않는 방법이다. keydown을 추천)

      (알파벳, 숫자, 띄어쓰기 등의 출력값이 변하는 키에서만 이벤트가 발생한다. esc나 shift 등의 기능적인 역할을 하는 키에서는 이벤트가 발생하지 않는다.)
      (하나의 키를 계속 누르고 있는 경우에도 처음 한번만 이벤트가 발생한다.)
      (한글에서는 이벤트가 발생하지 않는다.)

    • keyup: 키보드 버튼을 눌렀다 뗀 순간

    • keyboardEvent.key: 이벤트가 발생한 버튼의 값

    • keyboardEvent.code: 이벤트가 발생한 버튼의 키보드에서 물리적인 위치

  • input 태그 다루기

    • 포커스 이벤트

      focusin: 요소에 포커스가 되었을 때

      focusout: 요소에 포커스가 빠져나갈 때

      focus: 요소에 포커스가 되었을 때 (버블링 x)

      blur: 요소에 포커스가 빠져나갈 때 (버블링 x)

    • 입력 이벤트

      input: 사용자가 입력을 할 때

      (어떤 값이 입력될 때 발생하기 때문에 esc나 shift같은 입력과 관련 없는 키에는 이벤트가 발생하지 않는다)

      change: 요소의 값이 변했을 때

      (입력이 끝났을 때 발동)
profile
누구나 같은 팀으로 되길 바라는 개발자가 되자

0개의 댓글