본문 바로가기

카테고리 없음

JS #12- 웹 API 2 (DOM- 속성과 프로퍼티, 클래스와 스타일)

 

 

document.documentElement는 html을 뜻한다. 

firstChild,lastChild, childNodes를 통한 자식 노드 탐색...  등등을 할 수 있다. (이터럴)

  • 자식 노드(child node, children) 는 바로 아래의 자식 요소를 나타냅니다. 자식 노드는 부모 노드의 바로 아래에서 중첩 관계를 만듭니다. <head>와 <body>는 <html>요소의 자식 노드입니다.
  • 후손 노드(descendants) 는 중첩 관계에 있는 모든 요소를 의미합니다. 자식 노드, 자식 노드의 모든 자식 노드 등이 후손 노드가 됩니다.

 

 

document가 null으로 나오는 경우 = 해당 노드가 없다. 

 

 

 

탐색 프로퍼티를 이용한 이웃노드로의 이동, 탐색 프로퍼티는 크게 두개의 집합으로 나뉜다. 
모든 노드에 적용 가능한 parentNode, childNodes, firstChild, lastChild, previousSibling, nextSibling
요소 노드에만 적용 가능한 parentElement, children, firstElementChild, lastElementChild, previousElementSibling, nextElementSibling

 

 

getElement*, querySelector*로 요소 검색하기

 

 

matches('확인할 대상') : 가지고 있는지 확인하는 방법
가지고 있으면 true 반환 , 없으면 false 반환

closetst('찾을 대상') : 나, 나의 부모 중에 가장 인접한 것을 찾는 것 (형제 제외) 
찾은 값을 반환

 

 

querySelector /
querySelectorAll :자식 요소 중 주어진 CSS 선택자에 대응하는 요소 모두를 반환합니다.

 

 

 

<실습>

const first = document.querySelector('.first');

 

h2안에 있는 first 찾기! 

const h2 = document.querySelector('h2');
const second = h2.querySelector('.first') //h2 안에 있는 first를 찾겠다 (제한)

 

함수getNode 만들기 (두 번째 인자 context 고려하여) 

const getNode = (query, context = document) => {

    if(typeof query !== 'string') {
        throw new Error('getNode의 함수의 인수는 문자 타입이어야 합니다.');
    }

    if(context.nodeType !== document.DOCUMENT_NODE){
        context = document.querySelector(context);
    }
    return context.querySelector(node);
};

const node = getNode('.first');
console.log(node);

 

 

    <script src="./lib/dom/getNode.jss" defer></script>

ㄴ 함수를 따로 빼서 사용해주기 위해서 html 에 스크립트 경로를 하나 더 추가한다. 

 

 

DOM 노드의 계층 구조 꼭대기엔 EventTarget (부모)이 있는데,
Node는 Eventarget을, 다른 DOM 노드들은 Node 클래스를 상속받습니다. 

 

 

console.dir() -> 코드를 열거할 수 있는 것 

 

 

nodeName, tagName으로 태그 이름 확인하

const first = getNode('.first');
console.log(first.nodeType === document.ELEMENT_NODE);
console.log(first.nodeName === 'SPAN'); //항상 대문자

 

innerHTML : 요소 안의 HTML을 문자열 형태로 받아올 수 있다. 
요소 안 HTM을 수정하는 것도 가능하다!  (삭제 or 수정 가능)
해킹에 취약하기 떄문

 

// - innerHTML
first.innerHTML = 'likeLion'; //span 태그의 내용이 바뀐다.

// * 기존 내용 삭제
first.innerHTML = ''; // 삭제
// * 기존 내용과 새로운 내용을 합친 새로운 내용을 씀

first.innerHTML += '<strong>멋쟁이 </strong> 사자처럼'

 

innerHTML대신 textContent : 순수한 텍스트만 접

//setter
first.textContent = '멋사 9기 친구들' //값에만 접근, 태그에는 접근 불가능하다.

/getter
first.textContent;
 
hidden

 

<깜빡거리는 효과 실습>

let toggle = false;

setInterval(() => {
    getNode('h1').hidden = toggle ? true : false;
    toggle = !toggle
}, 500);

 

 

 

nodeType
요소 타입을 알고 싶을 때 사용합니다. 요소 노드라면 1을, 텍스트 노드라면 3을 반환합니다. 두 타입 외에도 각 노드 타입엔 대응하는 상숫값이 있습니다. 읽기 전용입니다.

nodeName/tagName
요소 노드의 태그 이름을 알아낼 때 사용합니다. XML 모드일 때를 제외하고 태그 이름은 항상 대문자로 변환됩니다. 요소 노드가 아닌 노드에는 nodeName을 사용하면 됩니다. 읽기 전용입니다.

innerHTML
요소 안의 HTML을 알아낼 수 있습니다. 이 프로퍼티를 사용하면 요소 안의 HTML을 수정할 수도 있습니다.

outerHTML
요소의 전체 HTML을 알아낼 수 있습니다. elem.outerHTML에 무언가를 할당해도 elem 자체는 바뀌지 않습니다. 대신 새로운 HTML이 외부 컨텍스트에서 만들어지고, elem이 삭제된 자리를 채웁니다.

nodeValue/data
요소가 아닌 노드(텍스트, 주석 노드 등)의 내용을 읽을 때 쓰입니다. 두 프로퍼티는 거의 동일하게 동작합니다. 주로 data를 많이 사용하는 편이며 내용을 수정할 때도 이 프로퍼티를 쓸 수 있습니다.

textContent
HTML에서 모든 <태그>를 제외한 텍스트만 읽을 때 사용합니다. 할당 연산을 통해 무언가를 쓸 수도 있는데 이때 태그를 포함한 모든 특수문자는 문자열로 처리됩니다. 사용자가 입력한 문자를 안전한 방법으로 처리하기 때문에 원치 않는 HTML이 사이트에 삽입되는 것을 예방할 수 있습니다.

hidden
true로 설정하면 CSS에서 display:none을 설정한 것과 동일하게 동작합니다.

 

 


 

 

속성과 프로퍼티 (중요!)

 

표준속성과 비표준 속성

id는 표준 속성이고, something은 비표준 속성이다. 

*표준 속성을 사용한 경우에만 1:1 매칭이 된다! 

 

 

비표준 속성값들을 가져오는 방법
ㄴ 일반적인 객체.속성 -> 으로는 접근 불가능 하므로, 다르게 접근해야한다. 

 

<getter함수> 

let getAtter = (node, prop) => {
    if ( typeof node ==='string') {
        node = document.querySelector(node); //getNode함수로 바로 사용하면 된다.
    }
    if ( typeof prop !== 'string') {
        throw new Error('getAtter 함수의 두 번째 인수는 문자 타입이어야 합니다.')
    }
    return node.getAttribute(prop)    
}

console.log(getAtter('.first', 'id'));

 

<setter 함수>

let setAttr = (node, prop, value) => {

    if( typeof node === 'string'){
        node = getNode(node);
    }
    if( typeof prop !== 'string') {
        throw new Error('setAtter 함수의 두 번째 인수는 문자 타입이어야 합니다. ')
    }
    if( typeof value !== 'string') {
        throw new Error('setAtter 함수의 세 번째 인수는 문자 타입이어야 합니다. ')
    }
    node.setAttribute(prop, value);
    console.log(node.getAttribute(prop));
}

setAttr('.first', 'class', 'active');

 

 

프로퍼티들은 대소문자를 가리지 않는다. 

 

DOM 프로퍼티 값의 타

 

style 속성의 경우, style 프로퍼티는 객체

setter의 역할을 할 수 있으나 getter의 역할을 하지 못한다. 

getComputed로 가져와야 한다. 

 

 

비표준속성이 표준속성으로 등록되었을때의 혼선을 막기 위해
비표준속성을 쓸때는 앞에 'data' 를 붙이는 관례를 가진다. 

ㄴ dataset을 통해서 값을 가져온다. 

ㄴ dataset 메서드를 사용하면 알아서 'data-' 으로 들어가게 된다. 

ex) order.dataset.name = 'data-name' 값을 변경

 

 

<실습>

//setter
first.dataset.name = 'tiger'

//getter
console.log(first.dataset);

first.dataset.animation = 'paused';

if(first.dataset.animation === 'play') {
    //...
}

 

attributes : 속성을 열거 
for(const value of first.attributes) {
    console.log(value);
}

 

 


문서 수정

 

 

노드 만들기 (레거시 방법)
const div = document.createElement('div'); //div 태그를 만들고
div.className = 'tiger';// tiger 클래스를 만들고
div.textContent = '멋쟁이 사자처럼'; //값을 넢는다.

document.body.append(div); //html에 삽입한다.
console.log(div);

 

 

insertAdjcent 를 이용한 방법  (매우 간단)
document.body.insertAdjacentHTML('beforeend', '<div class= "tiger"> 멋쟁이 사자처럼 </div>'); //html에 삽입한다.

 
const h1 = getNode('h1');

//h1 태그 바깥으로
h1.insertAdjacentHTML('beforeBegin','<li calss= "List">beforeBegin영화보기</li>');

//h1 태그 안쪽으로
h1.insertAdjacentHTML('afterBegin','<li calss= "List">afterBegin영화보기</li>');

//h1 태그 안쪽 아래로
h1.insertAdjacentHTML('beforeEnd','<li calss= "List">beforeEnd영화보기</li>');

//h1 태그 안쪽으로
h1.insertAdjacentHTML('afterEnd','<li calss= "List">afterEnd영화보기</li>');

결과값

 

 

 

 


 

 

스타일과 클래스

 

 

className

 

classList의 메서드

 


const first = getNode('.first');
// - className – 클래스 전체를 문자열 형태로 반환해주는 프로퍼티로 클래스 전체를 관리할 때 유용
// - classList – 클래스 하나를 관리할 수 있게 해주는 메서드로 개별 클래스를 조작할 때 유용

console.log(first.className);


first.classList.add('hello');
first.classList.remove('hello');

console.log(first.classList.contains('hello'));

 

 

<유틸 함수로 작성>

let addClass = (node, className) => {
    if(typeof node === 'string') {
        node = getNode(node);
    }
    node.classList.add(className);
}

let removeClass = (node, className) => {
    if(typeof node === 'string') {
        node = getNode(node);
    }
    node.classList.remove(className);
}

addClass('.first', 'second');
removeClass('.first', 'first');
let removeClass = (node, className) => {
    if(typeof node === 'string') {
        node = getNode(node);
    }
    if(!className) {
        node.className = ''; //클래스가 전달되지 않으면 전체 삭제
        return; //실행 끝
    }
    node.classList.remove(className);
}

ㄴ 전체 클래스 삭제하는 경우 node.className에 공백을 준다. 

 

 

 

 

요소 스타일에 접근
*모두 카멜케이스로 변경해야 접근 가능!

 

style의 프로퍼티를 삭제할 때에는 delete를 사용할 수 없다. 

document.body.style.display = "none";

-> 삭제하고 싶은 경우 document.body.style.display = "";

빈 문자열을 할당해야 한다. 

 

 

node.style.cssText를 이용해 `` 백틱으로 직접 넣을 수 있으나, 
이 방법은 기존의 스타일이 지워진다는 위험이 있기 떄문에 지양된다. 

 

 

 

getComputedStyle로계산된 스타일 얻기

 

1. node.style.class => 입력된 값을 읽거나, 수정할 수 있다. but, style 태그에 직접 적용된 속성이 아니면 읽어올 수 없다.

 

2. css에 적용된 (css cascade) 속성들은 getComputedStyle로 읽어와야한다. 

h1 {
    box-shadow: inset 0 0 20px green;
    margin: 0 auto;
}

 

 

 

style프로퍼티는 style 속성의 값을 읽을 때만 사용할 수 있음!

 

getComputedStyle(first)['color'];

이렇게 사용하 수 있다. 

 

 

<css 설정하기 실습>



let getCss = (node, prop) => {
    if(typeof node ==='string')node = getNode(node);
   
    console.log(getComputedStyle(node)[prop]);
}

let setCss = (node, prop) => {
    if(typeof node ==='string')node = getNode(node);

    node.style.background = prop
}

getCss('.first', 'backgroundColor');
setCss('.first', 'green');

 

삼항으로 위의 두 함수 구동

function css(node, prop, value) {
    !value ? getCss(node, prop) : setCss(node, prop, value);
}