본문 바로가기

html+CSS+JS/Java Script

[js] 정리: DOM Script 개념 / Script 위치 / 요소 element 선택 / 속성 attribute 선택 / class 추가 제거 / 요소&텍스트 추가 제거 / 이벤트

반응형

공부 영상

 

 

 DOM(Document Object Model) Script

html코드를 봤을 때 보이는 document안의 모든 것을 객체로 보는 형태.

html 객체 안에 head 객체와 body 객체가 들어가고, img 객체 안에 src 속성이 들어가는 식의 트리구조이다.

이러한 구조를 이용해 javascript로 element를 조작하는 것이 DOM 스크립트다.

 

용어)

element node: html, head, body, article, h1, section 등의 element 형태의 객체

text node : text 형태의 객체

 

 

 

 Script 위치

script 코드는 head나 body 어디에 넣어도 동작된다.

하지만 기본적으로 코드를 위에서부터 아래로 읽기 때문에 script 코드가 head에 있는 경우,

body의 내용을 아직 가져오지 않았기에 DOM 스크립트는 값을 구하지 못하거나 오류가 생길 수 있다.

 

이를 위해 body를 읽은 후, 동작하도록 하는 코드를 추가로 적을 수도 있지만,

body 최하단에 두면 body 내 element를 다 읽은 후 DOM 스크립트를 읽어 별도의 코드를 적지 않아도 문제가 발생하지 않는다.

또한 element를 먼저 화면에 구성한 후 script를 실행하게 되기 때문에 실제 전체 load 속도는 같더라도 사용자 화면에 DOM 구성이 먼저 보이게 되어 기다림이 적어지는 느낌(!)을 줄 수 있다.

이벤트 추가 함수 사용 jQuery 사용
window.addEventListener('DOMContentLoaded', function(){
    // addEventListener : 이벤트 추가 함수 (별도 구현x)
    // DOMContentLoaded : 이벤트 (DOM 구조 전부 로딩)
    // 즉, DOM 구조가 다 로드된 후, function 내 스크립트 실행

    스크립트 내용
})
$(function(){
    스크립트 내용
})

주의)

스크립트를 통해 DOM을 구성하는 경우에는 script 위치가 크게 중요하지 않습니다.

 

 

 

 다루고 싶은 Element 가져오기

설명용 body 코드

<body>
    <article id="main">
       <h1 class="txt">h1-0</span>
       <span class="txt">span-0</span>
       <span class="txt">span-1</span>
       <span>span-2</span>
       <span>span-3</span>
    </article>
</body>
선택자 종류   구성 형태 예시 결과 (개발자도구 - 콘솔창)
id
 형태 요소.getElementById('요소의 id 이름') <article id="main">...</article> 
 예시 var main = document.getElementById('main');
console.log(main);
element 태그명 형태 요소.getElementsByTagName('요소명') HTMLCollection(4) [span.txtspan.txtspanspan]
<span>span-0</span>

예시 var span =main.getElementsByTagName('span');
// 복수를 저장할 수 있기에 배열로 저장됨

console.log(span);
console.log(span[0]);
class 형태 요소.getElementsByClassName('클래스명') HTMLCollection(3) [h1.txt, span.txtspan.txt]
<h1 class="txt">h1-0<h1>
예시 var txt =main.getElementsByClassName('txt');
// main 안의 클래스 txt를 가진 요소들 저장
console.log(txt);
console.log(txt[0]);
css 선택자
(요즘 대세!!)
형태 요소.querySelector('css선택자')
// 1개일 경우

요소
.
querySelectorAll('css선택자')
// 2개 이상일 경우
querySelector로 복수 요소를 가져오는 경우,
첫번째 요소만 가져옵니다.
예시
var main2 = document.querySelector('#main');
console.log(main2);
NodeList [article#main]
<article id="main">...</article> 
var span2 = main2.querySelectorAll('span');
// 복수를 저장할 수 있기에 배열로 저장됨
console.log(span2);
console.log(span2[2]);
NodeList(4) [span.txtspan.txtspanspan]
<span>span-2</span>
var txt2 = main2.querySelectorAll('.txt');
console.log(txt2);
console.log(txt2[2]);
NodeList(3) [h1.txt, span.txtspan.txt]
<span>span-1</span>
var h1txt= main2.querySelectorAll('#main h1.txt');
console.log(h1txt);
console.log(h1txt[0]);
// 1개여도 배열로 저장되기에 선택 필요
NodeList(1) [h1.txt]
<h1 class="txt">h1-0<h1>

NodeListHTMLCollection의 다른 점은 내용을 찾아도 이해가 확실히 가지 않아서 쓰기가 힘들다.

더 공부한 뒤에 다시 봐야함.

 

 

 

 속성 가져오기

설명용 body 코드

<body>
    <div id="wrap">
        <h1 class="logo">
            <a href="http://kingji8life.tistory.com">KingJi</a>
        </h1>

      <img src="img/hello.jpg" alt="안녕">

    </div>
</body>
선택자 종류   구성 형태 예시 결과 (개발자도구 - 콘솔창)
속성 가져오기 형태 요소.getAttribute('속성명')
// return값 o, getter
http://kingji8life.tistory.com
예시 var link = document.querySelector('.logo a');
var linkAdd = link.getAttribute('href');
console.log(linkAdd);
속성 바꾸기 형태 요소.setAttribute('속성명', '바꿀 내용')
// return값 x, setter
http://kingji8life.tistory.com
http://google.com
예시 console.log(linkAdd);
link.setAttribute('href', 'http://google.com')
console.log(link.getAttribute('href'));

 

 

 

 클래스 추가/제거

설명용 body 코드

<body>
    <div id="wrap">
        <h1 class="logo hlogo logo-big">
            KingJi
        </h1>

    </div>
</body>
클래스   구성 형태 예시 결과 (개발자도구 - 콘솔창)
클래스 이름
구하기/바꾸기
형태 요소.className
// return값 o, getter
logo hlogo logo-big
header-logo
예시 var h1 = document.querySelector('#wrap>h1');
var h1Class = h1.className;
console.log(h1Class);
h1Class = 'header-logo';
console.log(h1Class);
클래스
추가하기
형태 요소.classList.add('추가할 클래스명') logo hlogo logo-big big-logo logo1
예시 var h1 = document.querySelector('#wrap>h1');
h1
.classList.add('big-logo', 'logo1');
var h1ClassAdded = h1.className;
console.log(h1ClassAdded);
클래스
삭제하기
형태 요소.classList.remove('제거할 클래스명') logo logo-big
예시 var h1 = document.querySelector('#wrap>h1');
h1
.classList.remove('hlogo');
var h1ClassRemove = h1.className;
console.log(h1ClassRemove);
클래스
포함여부
형태 요소.classList.contains('찾고 싶은 클래스명') true
false
예시 var h1 = document.querySelector('#wrap>h1');
var h1contain = h1.classList.contains('logo');
var h1notContain =  h1.classList.contains('kingji');
console.log(h1contain);
console.log(h1notContain);

 

 

 

 요소/텍스트 추가

설명용 body 코드

<body>
    <div id="wrap">
        <h1 class="logo hlogo logo-big">
            KingJi
        </h1>
        <ul class="lists"></ul>
    </div>
</body>
추가   구성 형태 예시 결과 (개발자도구 - 콘솔창)
요소 만들기 형태 document.createElement('만들고 싶은 요소')
<li></li>
예시 var listElem = document.createElement('li');
console.log(listElem);
요소 추가 형태 부모요소.appendChild('요소만들기')
콘솔창이 아닌 Elements화면에서 확인 가능

body코드
<div id="wrap">
    <h1 class="logo hlogo logo-big">
        KingJi
    </h1>
    <ul class="lists">
        <li></li>
    </ul>

</div>
예시 var lists = document.querySelector('.lists');
var listElem = document.createElement('li');
lists.appendChild('listElem');
내용 추가 형태 요소.innerText = '요소에 추가할 내용'; 콘솔창이 아닌 Elements화면에서 확인 가능

body코드
<div id="wrap">
    <h1 class="logo hlogo logo-big">
        kingji
    </h1>
    <ul class="lists"></ul>
</div>
예시 var logo = document.querySelector('.logo');
logo.innerText = 'kingji';
요소&내용
추가
형태 요소.innerHTML = '요소에 추가할 코드&내용'; 콘솔창이 아닌 Elements화면에서 확인 가능

body코드
<div id="wrap">
    <h1 class="logo hlogo logo-big">
        KingJi
    </h1>
    <ul class="lists">
        <li>hey</li>
    </ul>

</div>
예시 var lists = document.querySelector('.lists');
lists.innerHTML = '<li>hey</li>';

 

 

 

 이벤트

설명용 css 코드

<style>
    .menu-list { display:flex; }
    .menu-each { margin:.1em; padding:.3em; background-color:dodgerblue; color:#ffffff; list-style:none; }
    .menu-each.active { background-color: goldenrod; }
</style>

설명용 body 코드

<body>
    <div class="wrap">
        <button class="back-change">Change</button>
        <button class="back-return">Return</button>
        <nav class="gnb">
            <ul class="menu-list">
                <li class="menu-each">menu1</li>
                <li class="menu-each">menu2</li>
                <li class="menu-each">menu3</li>
            </ul>
        </nav>
    </div>
</body>

 

이벤트 구성 형태 예시
버튼 클릭 시,
영역 백그라운드 색상 변동
요소.addEventListener('이벤트 종류', 이벤트 발생 시 실행할 함수)
var btn = document.querySelector('.back-change');
var btnback = document.querySelector('.back-return);
var wrap = document.querySelector('.wrap');
function btnClickHandler() {
    wrap.style.background = 'dodgerblue';
}

btn.addEventListener('click', btnClickHandler);
btnback.addEventListener('click', function(){
    wrap.style.background = 'initial';
});
여러 메뉴버튼 중,
하나만 활성화 1

<활용>
this
반복문:for문
var 변수1 = document.querySelectorAll('요소');
// 형제요소가 많은 요소
var 변수2;
//활성화 된 요소 저장

function 함수(){
    if (변수2) {
        변수2.classList.remove('활성화용 클래스');
    }
    //변수2의 값이 존재하면 활성화 클래스 지우기
    this.classList.
add('활성화용 클래스');
    //this = 현 함수가 실행되는 대상
    변수2 = this;
}

for (var i=0; i<변수1.length; i++) {
    // 반복문. i = index 취급할 예정

    변수1[i].addEventListener('이벤트 종류', 이벤트 발생 시 실행할 함수);
}
var menuEach = document.querySelectorAll('.menu-each');
var currentMenu;
function menuClickHandler() {
    if(currentMenu) {
        currentMenu.classList.remove('active');
    }
    this.classList.add('active');
    currentMenu = this;
}

for(var i = 0; i<menuEach.length; i++) {
 menuEach[i].addEventListener('click',menuClickHandler);
}
여러 메뉴버튼 중,
하나만 활성화 2

<활용>
e(이벤트)
e.target
var 변수1 = document.querySelectorAll('부모요소');
// 형제요소가 많은 요소의 부모요소
var 변수2;
//활성화 된 요소 저장
function 함수(e){
    //함수의 addEventListener안에서 이벤트 핸들러로 실행될 때, 첫번째 매개변수(e)는 이벤트에 대한 정보를 가진 변수가 된다.
    if (변수2) {
        변수2.classList.remove('활성화용 클래스');
    }
    e.target.classList.
add('활성화용 클래스');
    //console에 e를 찍으면 뜨는 정보 중 
    변수2 = e.target;
}

변수1.addEventListener('이벤트 종류', 이벤트 발생 시 실행할 함수);
//함수를 1번만 써도 돼서 빨라짐
var menuList = document.querySelector('.menu-list');
var currentMenu;
function menuClickHandler(e) {
    if(currentMenu) {
        currentMenu.classList.remove('active');
    }
    e.target.classList.add('active');
    currentMenu = e.target;
}

menuList
.addEventListener('click',menuClickHandler);

 

Tip. 이벤트핸들러는 심플하게 두는 것이 차후 관리에 좀 더 편합니다.

수정 전 수정 후
var menuList = document.querySelector('.menu-list');
var currentMenu;
var menuChecked = document.querySelectorAll('.menu-each')[0];

function menuClickHandler(e) {
    if(currentMenu) {
        currentMenu.classList.remove('active');
    }
    e.target.classList.add('active');
    currentMenu = e.target;
}

menuList.addEventListener('click',menuClickHandler);

// 첫번째 버튼을 미리 시작
function menuClicked {
    menuChecked.classList.add('active');
    currentMenu = menuChecked;
}
menuClicked();
var menuList = document.querySelector('.menu-list');
var currentMenu;
var menuChecked = document.querySelectorAll('.menu-each')[0];

function clickActivate(elem) {
    elem.classList.add('active');
    currentMenu = elem;
}
function clickInactivate(elem) {
    elem.classList.remove('active');
}

function menuClickHandler(e) {
    if(currentMenu) {
        clickInactivate(currentMenu);
    }
    clickActivate(e.target);
}

menuList.addEventListener('click',menuClickHandler);

// 첫번째 버튼을 미리 시작

clickActivate(menuChecked);

 

반응형