[CodeStates-Section1]U11.JS/브라우저 DOM

hameee·2022년 11월 12일
0

CodeStates_Frontend_42기

목록 보기
11/39

1.후기

 DOM이 어렵다고 해서 걱정했었는데 재밌었다! 기본적인 HTML, CSS, JavaScript 지식에 DOM이 얹어지니 이제서야 웹 페이지를 만드는 큰 그림을 그릴 수 있었다.

 이번 주는 회원가입 창을 만드는 실습이 있었다. 사실 학습자료를 읽고 블로그 정리만 하며 공부하는 것에 조금 지쳐있었다. 하지만 실습을 하면서 내가 배운 것이 왜 필요하고 어떻게 쓰이지, 그리고 앞으로 어디에 초점을 맞추어 공부해야 하는지 등에 대한 답을 얻을 수 있어서 다시 힘을 얻었다.

 앞으로는 1)명령어를 찾아 정리하는 데 집중하기보다는, 명령문이 해당 문서에서 어떤 흐름으로 작동하는지, 2)한 문서에서 작성한 코드가 다른 문서와 브라우저에 어떤 영향을 미치는지를 이해하는 데 초점을 맞추어 공부할 것 같다.

2.새롭게 알게 된 것

Section1 Unit11 - [JS/브라우저] DOM
Chapter1. DOM 기초
Chapter2. DOM 다루기
Chapter3. 이벤트 객체

<Chapter1. DOM 기초>

1) script 위치 차이점
-head 안

-body 하단

-head 안에서 async 속성 사용

<script async src = "scrip.js"></script>

-head 안에서 defer 속성 사용(권장)

<script defer src = "scrip.js"></script>

출처: https://velog.io/@anjaekk/JS-Script%EC%82%BD%EC%9E%85-%EC%9C%84%EC%B9%98head-body-async-defer-%EB%B9%84%EA%B5%90

참고: head에 쓸 경우 null 이 콘솔에 출력되는 이유
자바스크립트에서 참조하는 html(html 태그들)이 아직 parsing되지 않았기 때문

2) console.dir()
console.log() 와 달리 DOM을 객체의 모습으로 출력.

3) 트리 구조

-특징: 부모 1개, 자식 1개 이상인 구조 반복

-element의 자식 요소를 모두 출력하는 법(반복문)

//html
<html>
  <head>
    <script defer src = "scope.js"></script>
  </head>
  <body>
    <div id='nav'>
      <div class='logo'></div>
      <div class='menu-wrapper'>
        <div class='menu'>menu</div>
        <div class='menu'>menu</div>
        <div class='menu'>menu</div>
        <div class='profile-photo'>photo</div>
      </div>
    </div>
    <div id='news-contents'>
      <div class='news-content-wrapper'>
        <div class='news-picture'>news-picture</div>
        <div class='news-title'>news-title</div>
        <div class='news-description'>news-description</div>
      </div>
    </div>
    <div id='footer'>footer</div>
  </body>
</html>
//javascript
function consoleLogAllElement(element){

element = document.querySelectorAll(${element} div)

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

<Chapter2. DOM 다루기>

1) CRUD
:Create, Read, Update, Delete
어떤 종류의 개발이나 컴퓨터 언어를 배울 때 가장 먼저 CRUD에 집중해야 함.
이 챕터에서는 document 객체를 통해서 HTML 엘리먼트를 만들고(CREATE), 조회하고(READ), 갱신하고(UPDATE), 삭제하는(DELETE) 방법을 뜻함. DOM에는 HTML에 적용(APPEND)하는 메서드가 따로 있으니 주의.

2) Create

const tweetDiv = document.createElement('div')

주의: 엘리먼트는 만들어졌지만 어떤 부모와도 연결되지 않은 상태

3) Append

document.body.append(tweetDiv)

4) Read
Document.querySelector(), Document.querySelectorAll()

const oneTweet = document.querySelector('.tweet')
const tweets = document.querySelectorAll('.tweet')

Document.querySelector(선택자): 선택자와 일치하는 문서 내 첫 번째 요소 반환
Document.querySelectorAll(선택자): HTML 요소들을 Array-like Object(유사 배열 객체)로 반환. 완전한 배열은 아니지만, for문 사용 가능.

참고. get으로 시작하는 DOM 조회 메서드
querySelector와 비슷한 역할을 하는 오래된 방식. 만약 이전 버전의 브라우저(인터넷 익스플로러) 호환성을 신경 써야 한다면, 이런 옛날 방식을 사용해야 할 수도 있음.

document.getElementsByClassName('class 이름'): class의 모든 자식 엘리먼트의 실시간 HTMLCollection을 반환
document.getElementById('id 이름'): 일치하는 id 속성을 가진 요소를 찾고, 이를 나타내는 Element 객체를 반환
document.getElementsByTagName('태그명'): 특정 태그를 가진 모든 요소를 유사 배열 객체로 반환

5) Append
마지막 자식 뒤에 삽입

const container = document.querySelector('#container')
const tweetDiv = document.createElement('div')
container.append(tweetDiv)

6) Update

const oneDiv = document.createElement('div');
console.log(oneDiv) // <div></div>

-엘리먼트에 문자열 입력: textContent

oneDiv.textContent = 'dev';
console.log(oneDiv) // <div>dev</div>

-엘리먼트에 class 추가: Element.classList.add()

oneDiv.classList.add('tweet')
console.log(oneDiv) // <div class="tweet">dev</div>

-엘리먼트에 id 추가: Element.id.add()

oneDiv.id = 'tweetID'
console.log(oneDiv) // <div id = "tweetID" class="tweet">dev</div>

주의: 아래 방법(setAttribute)으로 id 추가하는 것이 더 좋음

-요소에 속성 추가: Element.setAttribute(속성, 속성값)

oneDiv.setAttribut("id", "tweetiD");
console.log(oneDiv) // <div id = "tweetID" class="tweet">dev</div>

-classList vs. className
classList: class 추가, 삭제 가능
className: class 추가 불가(기존 class 초기화 후 추가하므로 다수의 class를 설정 불가)

7) Delete
-삭제하려는 요소의 위치를 알고 있는 경우
삭제할 요소.remove()(parameter 받지 않음, ()에 어떤 것을 넣어도 '.' 앞의 요소가 전체 삭제됨)

tweetDiv.remove()


-요소의 모든 자식 요소를 삭제하는 경우
방법1. 부모 요소.removeChild(제거할 자식 요소) + 첫 번째 자식이 있으면 삭제를 반복하는 반복문(권장)

const container = document.querySelector('#container');
while (container.firstChild) {
  container.removeChild(container.firstChild);
}

방법2. innerHTML에 공백 할당
주의: innerHTML은 XSS 공격에 굉장히 취약

document.querySelector('#container').innerHTML = '';

-첫 요소 1개만 남기고 삭제하는 경우
부모 요소.removeChild(제거할 자식 요소) + 자식이 2개 이상이면 삭제를 반복하는 반복문

const container = document.querySelector('#container');
while (container.children.length > 1) {
  container.removeChild(container.lastChild);
}

-특정 class를 가진 요소만 찾아서 지우는 경우
방법1. 배열이름.forEach() 사용

const tweets = document.querySelectorAll('.tweet')
tweets.forEach(function(tweet){
    tweet.remove();
})

-방법2. for...of 사용
querySelectorAll('.tweet')의 결과값이 배열로 취급되어 element가 'tweet'인 것을 삭제

const tweets = document.querySelectorAll('.tweet')
for (let tweet of tweets){
    tweet.remove()
}

8) HTML, CSS, JavaScript 분리
-역할
HTML: 요소 다 넣어놓음(보이든 안 보이든 다 넣어 놓고 id, class를 이용해 JS에서 조정)
CSS: 디자인
JavaScript: 기능

-분리 이유: 관심사 분리
디자인의 디테일한 요소가 자바스크립트 코드에 담기는 것을 방지하기 위해/따로 클래스를 이용하면, 해당 디자인을 디자이너가 쉽게 바꿀 수 있기 때문에/CSS는 디자인, 자바스크립트는 로직에 집중할 수 있게 하기 위해

9)<input> 속성의 value
type에 따라 다른 용도로 사용됨
-button, reset, submit: 버튼 내의 텍스트
-hidden, password, text: 입력 필드의 초기값(속성으로 사용할 때), 입력 필드의 값(.value로 값을 가져올 때)
-checkbox, image, radio: 해당 입력 필드 선택 시 서버로 제출되는 값
-file: value 사용 불가

예시. DOM에서 .value를 이용해 접근하기
주의: '.value'로 받은 값은 string으로 가져옴

//<input type="text" id="username">의 값 출력
console.log(document.querySelector('#username').value);

//새로운 값 설정
document.querySelector('#username').value = '새로운 값';

10) 화면상에서 표시되지 않게 만드는 속성(CSS)
display: none
실제 DOM 상: 엘리먼트가 존재
브라우저에서 표시할 때: 영역도 사라짐(레이아웃 상에 없는 것처럼 취급)

visibility: hidden
실제 DOM 상: 엘리먼트 존재
브라우저 표시할 때: 영역은 남아 있음

11) Node, Element
Node가 상위 개념
DOM은 document 객체를 통해 HTML(root document)에 접근

12) 요소 노드(element node)
HTML 태그
속성 노드를 가질 수 있는 유일한 노드

HTML 문서 ---> DOM ---> 브라우저

출처: https://sosocodingday.tistory.com/215

13) 정규표현식
문자열에서 특정 문자 조합을 찾기 위한 패턴, 외우지 말고 검색해서 쓰기

// [유효성 검증 함수]: 최소 8자 이상하면서, 알파벳과 숫자 및 특수문자(@$!%*#?&) 는 하나 이상 포함
function strongPassword(str) {
  return /^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/.test(str);
}

14) 삼항연산자
-형식

condition ? exprIfTrue : exprIfFalse

-예시

15)
-부모 노드.insertBefore(삽입 할 노드, 기준점 노드): 기준점 노드 앞에 노드 삽입, 기준점 노드가 null이면 맨 마지막 자식이 됨
-복제되어야 할 노드.cloneNode(true):노드 복제(자식까지)
-복제되어야 할 노드.cloneNode(false):노드 복제(자식X)
-부모 노드.appendChild(생성할 노드): 특정 부모 노드의 자식 노드 리스트 중 마지막 자식으로 삽입, 생성할 노드가 document에 이미 있는 노드라면 위치 이동 효과(복사 아님)

//html(appendChild 적용 전)
<div class="a">
    <span></span>
</div>
<div class="b"></div>
//javascript
const span = document.querySelector(‘span’); 
const divB = document.querySelector(.b’); 
divB.appendChild(span);
//html(appendChild 적용 후)
<div class="a"></div> //class a에 있던 span은 사라짐(이동)
<div class="b">
	<span></span>
</div>

-있을 것 같지만 없는 것: prependChild(), insertAfter()

16) append, appendChild

<Chapter3. 이벤트 객체>

1) 이벤트 핸들러
이벤트가 발생할 때 실행되는 함수

2) 함수 할당, 함수 실행 값 할당
이벤트 객체 사용 시 함수를 할당해야 함

function handler() {
  console.log('버튼이 눌렸습니다!');
}

btn.onclick = handler;//함수를 할당, ()가 있으면 함수 실행 값이 할당됨

3) onclick vs. addEventListener('click', 함수)
-형식

btn.onclick = function() {
  console.log('버튼이 눌렸습니다!');
}
btn.addEventListener('click', function() {
  console.log('버튼이 눌렸습니다!');
});

-onClick, addEventListener 주의점
이벤트가 일어날 시 함수 실행이 되어야 하므로
함수를 할당(O)
함수의 실행값 할당(X)

-addEventListener 특징
최신 문법
자동으로 event 객체 생성(event.target 사용 가능)
이벤트 하나 이상의 핸들러(함수) 등록 가능(onclick은 덮어쓰기 됨)
HTML 요소뿐만 아니라 모든 DOM 요소에 대해 동작
버블링/캡처링과 같은 세밀한 제어 가능
이벤트 이름에 'on' 접두사 붙지 않음

4) event.target
타깃 요소: 이벤트가 발생한 가장 안쪽 요소
접근 방법: event.target
-예시

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>이벤트 객체</title>
  </head>
  <body>
    <button>아메리카노</button>
    <button>카페라떼</button>
    <script>
      let menus = document.querySelectorAll("button"); //모든 버튼을 가져옵니다.

      let btnAmericano = menus[0];
      let btnCaffelatte = menus[1];

      function handleClick(event) {
        let currentMenu = event.target.textContent;//이벤트 객체의 target 속성 안에 들어있는 태그의 textContent를 가져와라
        console.log(currentMenu + "를 클릭하셨습니다.");
      }

      btnAmericano.onclick = handleClick;
      btnCaffelatte.onclick = handleClick; // 이상으로 for 문으로 충분히 구현할 수 있는 내용입니다.
    </script>
  </body>
</html>

5) 이벤트 버블링, 캡처링, 차단

-이벤트 버블링(addEventListener에서의 기본값)
: 타겟 요소 ---> 최상위 부모 요소(document, window까지)로 이벤트 전파

addEventListener(type, listener, false)

-이벤트 캡처링
: 타겟 요소 ---> 최하위 자식 요소로 이벤트 전파

addEventListener(type, listener, true)

-이벤트 차단
: event.stopPropagation() 삽입

// 이벤트 버블링
document.querySelector('.three').addEventListener('click', function(event) {
  event.stopPropagation(); // 이벤트 차단
  alert('three');
});

참고 사이트: https://frontsom.tistory.com/12

6) Number.isNaN()
주어진 값이 NaN인지 판별
false ---> 숫자임
true ---> 숫자 아님

7) 문서 간 연결
CSS -- selector -- HTML -- querySelector() -- JavaScript

8) event.target, event.currentTarget
event.target: 실제 클릭한 요소
event.currentTarget: 현재 실행 중인 핸들러가 할당된 요소

0개의 댓글