Vanilla Javascript
HTML과 CSS로 웹 페이지를 꾸미고 나면, Vue나 React같은 다양한 프레임워크로 기존의 CSS만으로는 구현할 수 없는 신기한 반응형 웹 동작을 구현할 수 있습니다. 하지만 그런 도구 없이 순수 자바스크립트로도 가능한데요, 추가적인 라이브러리 없이 자바스크립트만으로 웹 동작을 코딩하는 것을 vanilla javascript라고 합니다. vanilla javascript를 공부하면 자바스크립트에 대해 좀 더 깊고 자세히 이해할 수 있게 되고, 추후 공부할 다른 프레임워크에도 빠르게 적응할 수 있게 됩니다.
자바스크립트 파일 연결하기
HTML파일 내에서 자바스크립트 파일과 연결하는 코드를 추가할 수 있습니다.
<body>
...
<script src="index.js"></script>
</body>
이렇게 body태그 내부의 script태그의 src속성에 원하는 자바스크립트의 파일을 넣어주면 됩니다.
태그 선택하기
HTML코드의 태그들을 id, class, 태그명을 이용해 선택할 수 있습니다.
- id : id의 속성값은 html내에 하나 밖에 존재하지 않기 때문에 id를 이용한 태그 선택 시 하나의 태그만이 리턴됩니다.
- class : 그러나 class의 속성값은 다수의 태그에 사용될 수 있기 때문에 class를 이용한 태그 선택 시 다수의 태그들이 HTMLCollection이란 이름의 유사배열 형태로 저장되어 리턴됩니다.
- 태그 이름 : 태그 이름을 기반으로 한 태그 선택 역시 다수의 태그들이 선택될 수 있기 때문에 HTMLCollection이란 이름의 유사배열 형태로 리턴됩니다.
이렇게 선택한 태그를 출력하면 해당 태그들의 내부 html 코드 내용물들을 전부 출력하게 됩니다.
// id를 이용한 태그 선택
const myTag1 = document.getElementById("id_0");
console.log(myTag1)
// class를 이용한 태그 선택
const myTags2 = document.getElementsByClassName("class_0");
// 태그 이름을 이용한 태그 선택
const myTags3 = document.getElementsByTagName('h1');
// 배열처럼 사용 가능한 유사배열
console.log(myTags2[0])
console.log(myTags2[1])
for (let i = 1; i < myTags3.length; i++) {
if (i % 2 == 0) {
console.log(myTags3[i]);
}
}
근데 이런 방식 말고 CSS선택자를 이용해 태그를 선택할 수도 있는데요, 이 방법으로 모든 종류의 태그를 선택할 수 있으니 좀 더 범용적이라 볼 수 있습니다.
const tagA = document.querySelector(".class_0");
const tagB = document.querySelector("#id_0");
const tagC = document.querySelector("p");
const tagD = document.querySelectorAll(".class_1");
querySelector 메소드는 다수의 요소를 가지고 있는 유사배열을 저장하는게 아니라, 가장 첫번째 요소만을 저장합니다.
querySelectorAll 메소드를 사용하게 되면 해당 태그들을 모두 담고 있는 NodeList라는 이름의 유사배열을 리턴하게 됩니다.
만약 존재하지 않는 속성값을 넘겨주게 되면 다음과 같은 결과를 리턴합니다.
const myTag1 = document.getElementById("wrong_id"); // null
const myTag2 = document.getElementsByClassName("wrong_class"); // [] (빈 array)
const myTag3 = document.querySelector("wrong_tag"); // null
const myTag4 = document.querySelectorAll("wrong_tag"); // [] (빈 array)
DOM
DOM은 문서 객체 모델이란 뜻으로, Document Object Model의 약자입니다. 이는 웹페이지에 나타나는 html문서 전체를 객체로 표현한 것으로, 위에서 사용했던 document객체가 최상단 객체로서의 역할을 하며 웹문서로의 진입점 역할을 합니다. 따라서 DOM을 활용하면 html 태그들을 객체처럼 다룰 수 있게 됩니다.
사실 브라우저의 최상단 객체는 window라는 객체인데요, 웹 문서에 접근하는 document나 콘솔창에 로그를 띄울 때 사용하는 console도 모두 window에 속해있습니다. 이처럼 window같은 객체를 전역객체(Global Object)라고 합니다.
객체의 값이나 속성을 알기 위한 방법으로는 console.log와 console.dir이 있습니다.
console.log(obj); // html형태로 출력
console.dir(obj); // 객체의 속성들을 출력
HTML코드를 확인해보면 여러 태그들이 있고, 어떤 태그는 다른 태그를 감싸고 있으며 또 어떤 태그는 다른 태그 안에 있는 계층구조인데요, document 객체를 최상위로 한 객체들도 결국은 계층구조를 이루게 됩니다. 이를 DOM트리 라고 합니다.
이 DOM트리의 각 객체들을 노드라고 부르고, 특히 상위에 있는 노드를 부모 노드, 하위에 있는 노드를 자식 노드라고 부릅니다. 그리고 head나 body같이 태그를 표현하는 노드를 요소 노드라고 하고, 문자열을 표현하는 노드를 텍스트 노드라고 부릅니다. 텍스트 노드는 요소 노드의 자식 노드이며, 자식 노드를 가질 수 없습니다.
이런 객체들 간의 관계를 이용해서 특정 요소 노드(태그)에 접근할 수 있습니다.
const element = document.querySelector('#list-1');
element.children // 모든 자식 요소
element.firstElementChild // 첫번째 자식 요소 하나
element.lastElementChild // 마지막 자식 요소 하나
element.parentElement // 부모 요소 하나
element.previousElementSibling // 바로 이전의 형제 요소 하나
element.nextElementSibling // 바로 다음의 형제 요소 하나
// 응용: 부모 태그의 형제 노드들 중 바로 다음에 있는 형제 노드
element.parentElement.nextElementSibling
요소 노드
요소 노드의 태그를 선택한 후 HTML코드나 내부 텍스트를 변환해 봅시다. 태그 선택 후 다음 속성들을 이용해 접근할 수 있습니다.
- element.innerHTML : 요소 노드 내부의 HTML 코드를 문자열로 리턴해줍니다.
- element.outerHTML : 요소 노드 자체의 전체적인 HTML 코드를 문자열로 리턴해줍니다.
- element.textContent : 요소 안의 내용들 중에서 HTML태그 부분은 제외하고 텍스트만 가져옵니다.
위 속성들을 이용해 내부의 HTML이나 텍스트 자체를 수정할 수 있습니다.
const element = document.querySelector('#list');
// 기존 내용을 완전히 다른 내용으로 대체합니다
element.innerHTML = "<li>Exotic</li>";
element.outerHTML = "<ul id="new-list"><li>Exotic</li></ul>";
element.textContent = "new text";
// 기존 내용에 새로운 리스트를 추가하는 법
element.innerHTML = element.innerHTML + "<li>Exotic</li>";
위와 같이 기존의 문서 구조를 덮어쓰는 방식이 아니라, 요소 노드를 직접 생성해서 그 요소만 필요한 곳에 추가할 수도 있습니다. 총 3단계로 구분해서 볼 수 있습니다.
1. 요소 노드 만들기 : document.createElement("태그이름")을 통해 요소 노드를 만듭니다.
2. 요소 노드 꾸미기 : 만든 요소 노드의 textContent, innerHTML 속성을 이용해 내부 내용을 생성합니다.
3. 요소 노드 추가하기 : 들어갈 노드의 prepend, append, after, before 메소드를 이용해 만들어 준 노드를 넣을 수 있습니다.
const element = document.querySelector('#list');
const new_element = document.createElement('li');
new_element.textContent = '새로운 내용';
element.prepend(new_element); // prepend: 첫번째 자식 노드로 추가해줍니다
element.append(new_element); // append: 제일 마지막 자식 노드로 추가해줍니다
element.before(new_element); // before: 바로 앞에 형제 노드로 추가해줍니다
element.after(new_element); // after : 바로 뒤에 형제 노드로 추가해줍니다
// 이렇게 직접적으로 문자열을 넣어줄 수도 있고, 복수의 값을 넣어줄 수도 있습니다
element.before("문자열", new_element);
노드를 삭제하거나 다른 곳으로 이동시켜 봅시다. 삭제는 remove() 메소드를 사용하면 되고, 이동은 요소 노드를 추가할 때 사용했던 메소드들을 이용해 구현할 수 있습니다.
const element = document.querySelector('#list');
const element2 = document.querySelector('#list2');
element.remove();
element.children[2].remove(); // 세번째 자식 노드를 삭제합니다
// element가 가리키는 노드의 2번째 자식 노드 뒤로 element2가 가리키는 노드의 3번째 자식 노드 이동
element.children[1].after(element2.children[2])
HTML 속성
html 파일의 태그의 속성들은 요소 노드의 프로퍼티가 됩니다. 예를 들어 이런 html 파일이 있다고 가정해 봅시다.
<h1 id="example">제목1</h1>
h1태그를 가리키는 요소 노드가 있다고 했을 때 해당 요소 노드의 속성에 접근하고, 새로운 속성을 추가하거나 기존에 있던 속성을 제거해봅시다.
const element = document.querySelector("h1");
// 해당 노드의 id속성에 접근
element.getAttribute("id"); // example
// 새로운 class속성에 list라는 속성 값을 추가(수정)
element.setAttribute("class", "list"); // <h1 id="example" class="list">제목1</h1>
// 기존의 id 속성 제거
element.removeAttribute("id"); //<h1 class="list">제목1</h1>
스타일
노드의 style 속성을 이용해 마치 CSS를 사용하듯 스타일을 입힐 수가 있습니다.
const element = document.querySelector("#list")
element.children[0].style.textDecoration = 'line-through';
element.children[0].style.backgroundColor = '#DDDD';
다만 속성을 지정할 때 textDecoration 같은 속성은 원래 text-decoration지만 카멜표기법으로 인해 -을 빼주고 textDecoration 라고 씁니다.
하지만 style속성에 직접 접근해 스타일을 바꿔주는 코딩 방식 보다는 CSS파일에 미리 클래스 스타일을 작성해 놓은 다음 노드에 해당 클래스의 속성값을 추가하거나 삭제하는 방식의 코딩이 훨씬 더 깔끔합니다.
// element가 가리키는 노드의 class에 exampleclass라는 속성값 추가
element.children[1].className = "exampleclass";
그러나 위의 방식대로 하면 태그의 클래스 속성값 전체가 바뀌는 거라 기존에 있던 클래스 속성값은 사라지게 됩니다.
따라서 기존의 클래스 속성들은 유지하면서 새로운 클래스를 추가하기 위해선 classList라는 것을 사용하면 됩니다.
classList는 클래스의 속성값들을 유사배열로 다루는 프로퍼티로, add, remove, toggle 같은 메소드들을 제공합니다.
const element = document.querySelector("li")
element.classList.add("done"); // done이라는 속성값을 추가합니다
element.classList.remove("done"); // done이라는 속성값을 제거합니다
element.classList.toggle("done"); // done이라는 속성값이 없으면 추가하고 있으면 제거합니다
// add와 remove 메소드는 여러 클래스값들을 넣거나 삭제할 수 있습니다
element.classList.add("done", "doing");
element.classList.remove("done", "doing");
'프론트엔드 > Vanilla JS' 카테고리의 다른 글
[JS] 이벤트 핸들링 (0) | 2021.11.08 |
---|