이글은 유튜버 김버그의 DOM 영상 시리즈를 보고 정리한 글입니다.
#1 DOM 이란?
자바스크립트에게 HTML 이란, 문자열입니다. 그 이상 그 이하도 아닙니다.
보여주는 역할을 하는 건 HTML, CSS가 지배적인데 자바스크립트는 이 녀석들을 컨트롤합니다.
이 문자열인 HTML을 자바스크립트가 알아들을 수 있게 바꾸는 작업을 프로그래밍 언어에서는 'parse'라는 말을 많이 쓰는데,
문자를 의미있는 객체로 바꾸는걸 parsing이라고 하고...
뭘로 바꾸냐 하면 node로 바꾸는 것입니다.
node는? 종류같은 것 이라고 생각하면 됩니다.
제일 중요한건 document, element 이고
돔은 문자일 뿐인 HTML를 의미있는 노드객체로 바꿔서 추가적인 기능을 할 수 있게 해줍니다.
append, remove, createElement()를 자주 쓰고
innerHTML innerText 기억해도 충분합니다.
Element Nodes 의 element는 HTML 태그를 뜻합니다.
getAttribute() -> 속성 가져오기
setAttribute()
removeAttribute()
classList 기억하세요
함수이름을 get, has, set이 개발자들이 많이 쓰는 동사 입니다.
값을 가지고 알고 싶으면 get, 있는지없는지 has, 어떤 값을 지정하고 싶을때 set을 하는구나 라고 알고 넘어가세요.
classList.add()
classList.remove()
classList.toggle -> 있으면 없애고, 없으면 추가해주는 것입니다.
이게 최신 버전이고,
전에는 parent.setAttribute('class', 'hello') 이런식으로 썼는데 그러면 class가 원래 있었으면, 'hello'로 덮어씌워지기 때문에 클래스를 지정해서 추가하고 삭제할 수 있는 classList를 사용하는것이 더 편리할 수 있습니다.
parent.innerHTML = '<div>hello</div>'
parent.innerText = 'hello'
#2 DOM 이벤트
event handler = event listener = event 콜백함수
가장 보편적인 아이가 addEventListener()
onclick()은 옛날에 사용하던 방식이라 addEventListener를 추천합니다
DOM Event Types 중 알아놓아야 할 것들
Load -> Fires when an asset (HTML page, image, CSS, frameset, <object>, or JavaScript file) is loaded
// 페이지 로드가 다 끝났을 때
resize -> Fires when a document view has been resized; this event type is dispatched after all effects for that occurrence of resizing of that particular event target have been executed by the user agent
// 화면 사이즈 줄이고 키우고 할 때
scroll -> Fires when a user scrolls a document or an element
// 유저가 스크롤 중이다
Focus events
blur -> Fires when an element loses focus either via the mouse or via tabbing
// 포커스 했다가 다른걸 선택할 때
focus -> Fires when an element receives focus
// 어떤 요소를 클릭하거나 포커스 상태 일 때
Form events
change -> Fires when a control loses the input focus and its value has been modified since gaining focus
// input 요소나 텍스트 에리아의 값이 바꼈을 때
submit -> Fires when a form is submitted
// 서브밋 버튼을 눌렀을 때
Mouse events
click -> Fires when a mouse pointer is clicked (or the user presses the Enter key) over an element. A click is defined as a mousedown or mouseup over the same screen location. The sequence of these events is mousedown>mouseup>click. Depending on the environment configuration, the click event may be dispatched if one or more of the event types mouseover, mousemove and mouseout occur between the press and release of the pointing device button. The click event may also be followed by the dbclick event.
// 가장 많이 사용하는 이벤트
mousedown -> Fires when a mouse pointer is pressed over an element.
// 마우스가 눌려짐을 당했다. (click과 mousedown의 뉘앙스를 구분해야합니다..)
mouseenter -> Fires when a mouse pointer is moved onto the boundaries of an element or one of its descendent elements. This event type is similar to mouseover, but differs in that it does not bubble and it must not be dispatched when the pointer device moves from an element onto the boundaries of one of its descendent elements.
// 마우스가 어느곳에 진입했냐, 들어갔냐
mouseleave -> Fires when a mouse pointer is moved off the boundaries of an element and all its descendent elements. This event type is similar to mouseout, but it differs in that it does not bubble and it must not be dispatched until the pointing device has left the boundaries of the element and the boundaries of all its children.
// 마우스가 진입했다가 나가냐 - 일종의 hover 느낌과 비슷
mouseup -> Fires when a mouse pointer button is released over an element.
// 마우스 다운 했다가 손 뗄때
Keyboard events
keydown -> Fires when a key is initially pressed. This is sent after any key mapping is performed, but before any input method editors receive the keypress. This is sent for any key, even if it doesn't generate a character code.
// 특정 키를 눌렀을 때. 가장 많이 쓰는 것은 esc 눌렀을 때. 팝업 꺼지게 만드는 것 등!
keyup -> Fires when a key is released. This is sent after any key mapping is performed, and always follows the corresponding keydown and keypress events.
// keydown을 눌렀다가 뗐을 때.
Touch events
모바일에서는 마우스가 없어서 터치하는 것 감지
touchstart, touchend, touchmove, touchenter, touchleave, touchcancel
절대로 다 외울필요가 없고, 내가 사용하고 싶은 이벤트가 있다면 검색을 해보고 있다면 사용을 하고, 없으면 만드는 방식으로 하면 됩니다.
#3 DOM 이벤트 플로우
프론트엔드 개발자라면 이벤트를 어떻게 사용하는지 뿐만 아니라 이벤트가 어떻게 작동하는지도 알아야합니다.
이벤트의 시발점 (The Ultimate Cause) -> div를 클릭하는 이벤트를 실행했다고 하면, div가 됩니다
하지만 div는 body의 위에, body는 html의 위에 있는 형식이기 때문에 div를 누르게되면 다같이 실행을 시킵니다.
body와 html은 이벤트를 탑승하게 됩니다. 부모관계에 있는 모든 관계자들은 전원 실행됩니다. 연좌제!
current target -> 이벤트의 진짜 주인
target -> 이벤트의 시발점
참고로 currentTarget과 target은 이벤트 객체가 제공하는 대표적인 공통 property입니다.
div를 클릭하는 이벤트를 실행했다고 예를 들면,
div 에게 currentTarget : div, target: div
body 에게는 currentTarget : body, target: div
html 도 마찬가지로 currentTarget: html, target: div
이렇게 current target과 target을 분리해서 생각해야 합니다.
이러한 event flow는 디폴트로 정해져 있습니다.
* propagate : 전파하다
Capture phase ( = propagate up ) : 브라우저에서 가장 가까운 순서부터 시작
html -> body -> div
밑에서 위로
Target phase : 그 이벤트가 시작된 당사자 실행
div
Bubble phase ( = propagate down ) : 다시 내려오는 과정
div -> body -> html
위에서 밑으로
물이 아래로 흐르듯 이벤트 플로우도 캡 - 타 - 버 순으로
currentTarget과 target이 일치하지 않는 경우,
event flow phase 중 어느 단계에서 실행되고 싶은지 선택 capture vs. bubble
기본 설정값은 bubble입니다. 이게 합리적이라고 생각하는 이유는 div를 선택했는데 div보다 먼저 html과 body가 실행되는게 이상하다고 생각하기 때문.. 주객 전도 느낌
const html = document.documentElement const body = document.body const div = document.querySelector('div') div.addEventListener('click', function () { console.log('DIV') // div 이벤트를 실행하니까 언제 실행할지 지정 X }) body.addEventListener( 'click', function() { console.log('BODY') }, true ) // true -> 캡쳐 때 실행해라 html.addEventListener( 'click', function () { console.log('HTML') }, true // true -> 캡쳐 때 실행해라 ) // 출력결과 // 1. HTML // 2. BODY
#4 필수 DOM 이벤트 객체 메소드 2개
나는 그냥 div 눌렀으면 div만 실행 됐으면 좋겠는데 라고 생각할 수 있는데,
일단 브라우저가 캡쳐 프레이즈부터 가서 버블로 가는건 절대 막지 못합니다. 디폴트이기때문에..
하지만 전파하는 건 막을 수 있습니다.
1. e.stopPropagation()
// -> 내 이후로 전파하는 걸 다 멈춰라!
2. preventDefault()
꼭 기억하세요.
앵커를 누르면 href로 페이지를 이동하는게 default 로직이고, 체크박스를 누르면 체크되는 것도 그렇죠.
하지만 그런 디폴트 로직을 막고싶을때 사용합니다.
예를들어, 버튼을 누르면 submit이 되는데,
사용자가 내용을 입력하기 전까지 submit 하지못하게 막는 것이 있습니다.
노마드 코더에서 클론코딩 때 사용한적 있음 !
'DOM > 기초' 카테고리의 다른 글
DOM 복습하기 (0) | 2021.11.30 |
---|---|
모던 자바스크립트 DOM 탐색하기 (0) | 2021.07.06 |
textContent vs innerText vs innerHTML (0) | 2021.06.29 |
setAttribute (0) | 2021.06.29 |
querySelector (0) | 2021.06.29 |