어트리뷰트
1. 어트리뷰트 노드와 attributes 프로퍼티
- HTML 문서 구성 요소인 HTML 요소는 여러 개의 어트리뷰트(속성)를 가질 수 있음
- HTML 요소의 동작을 제어하기 위한 추가적인 정보를 제공
- HTML 요소의 시작 태그에 어트리뷰트 이름='어트리뷰트 값' 형식으로 정의
- HTML 문서가 파싱될 때 HTML 요소의 어트리뷰트는 어트리뷰트 노드로 변환되어 요소 노드와 연결 (HTML 어트리뷰트 당 하나의 어트리뷰트 노드 생성)
- 어트리뷰트 노드의 참조는 유사 배열 객체이자 이터러블인 NamedNodeMap 객체에 담겨서 요소 노드의 attributes 프로퍼티에 저장됨 → Element.prototype.attributes 프로퍼티로 취득 가능
- attributes 프로퍼티는 getter 만 존재하는 읽기 전용 접근자 프로퍼티로 요소 노드의 모든 어트리뷰트 노드가 담긴 NamedNodeMap 객체 반환
2. HTML 어트리뷰트 조작
- Element.prototype.getAttribute/ setAttribute 메서드를 사용하면 요소 노드에서 메서드를 통해 직접 HTML 어트리뷰트 값을 취득/ 변경 가능
- Element.prototpye.hasAttribute(attributeName)으로 특정 HTML 어트리뷰트가 존재하는지 확인
- Element.prototype.removeAttribute(attributeName)으로 특정 HTML 어트리뷰트 삭제
<!DOCTYPE html>
<html>
<body>
<input id="user" type="text" value="Echichi" />
</body>
<script>
const $input = document.getElementById("user");
// value 어트리뷰트 값 취득
const inputVal = $input.getAttribute("value");
console.log(inputVal); // Echichi
// value 어트리뷰트 값 변경
$input.setAttribute("value", "echichi");
console.log($input.getAttribute("value")); // echichi
//value 어트리뷰트 존재 확인
if ($input.hasAttribute("value")) {
//value 어트리뷰트 삭제
$input.removeAttribute("value");
}
console.log($input.hasAttribute("value")); // false
</script>
</html>
3. HTML 어트리뷰트 vs. DOM 프로퍼티
html 과 DOM 의 관계
HTML 문서는 웹 페이지의 구조를 정의. 브라우저가 아닌 이 HTML 문서를 로드할 때 이를 분석하여 DOM이라는 구조를 생성하는데 DOM 은 HTML 문서의 구조, 스타일, 내용 등을 객체 모델로 표현한 것. 각 HTML 요소는 DOM 에서 하나의 요소 노드로 표현되며, HTML 어트리뷰트는 해당 요소 노드의 프로퍼티로 변환됨
HTML 어트리뷰트와 DOM 프로퍼티는 초기 상태에서는 같은 값을 공유할 수 있지만 웹 페이지가 동작하면서 이들은 서로 독립적으로 변할 수 있음. 예를 들어, 사용자가 폼 필드에 새로운 값을 입력하면 이는 DOM의 value 프로퍼티를 변경하지만 HTML 어트리뷰트는 그대로 유지됨
- 요소 노드 객체에는 HTML 어트리뷰트에 대응하는 프로퍼티 존재 (DOM 프로퍼티들은 HTML 어트리뷰트 값을 초기값으로 가짐)
- HTML 어트리뷰트 역할은 HTML 요소의 초기 상태를 지정하는 것 (HTML 어트리뷰트 값은 HTML 요소의 초기 상태를 의미하며 불변)
- 요소 노드는 상태를 가지고 있으며 초기 상태와 최신 상태를 관리해야함
- 요소 노드의 초기 상태는 어트리뷰트 노드가 관리하며 요소 노드의 최신 상태는 DOM 프로퍼티가 관리
3-1. 어트리뷰트 노드
- HTML 어트리뷰트로 지정한 HTML 요소의 초기 상태는 어트리뷰트 노드에서 관리
- 어트리뷰트 노드에서 관리하는 값은 사용자의 입력에 의해 상태가 변경되어도 변하지 않고 HTML 어트리뷰트로 지정한 HTML 요소의 초기 상태를 그대로 유지
- 어트리뷰트 노드가 관리하는 초기 상태 값을 취득하거나 변경하려면 getAttribute/setAttribute 메서드를 사용
- getAttribute 은 초기 상태 값으로 결과는 언제나 동일
- setAttribute 은 초기 상태 값을 변경
3-2. DOM 프로퍼티
- 사용자가 입력한 최신 상태는 HTML 어트리뷰트에 대응하는 요소 노드의 DOM 프로퍼티가 관리
- DOM 프로퍼티는 사용자의 입력에 의한 상태 변화에 반응하여 언제나 최신 상태 유지
- 사용자 입력에 의한 상태 변화와 관계 없는 어트리뷰트와 DOM 프로퍼티는 항상 동일한 값으로 연동
<!DOCTYPE html>
<html>
<body>
<input id="user" type="text" value="Echichi" />
</body>
<script>
const $input = document.getElementById("user");
// 사용자가 input 요소의 입력 필드에 값을 입력할 때마다 input 요소 노드의 value 프로퍼티 값,
// 즉 최신 상태 값을 취득
// value 프로퍼티 값은 사용자의 입력에 의해 동적으로 변경
$input.oninput = () => {
console.log("value 프로퍼티 값", $input.value);
};
// getAttribute 메서드로 취득한 HTML 어트리뷰트 값, 즉 초기 상태 값은 변하지 않고 유지
const inputVal = $input.getAttribute("value");
console.log(inputVal); // Echichi
</script>
</html>
3-3. HTML 어트리뷰트와 DOM 프로퍼티의 대응 관계
- id 어트리뷰트와 id 프로퍼티는 1:1 대응하며 동일한 값으로 연동
- input 요소의 value 어트리뷰트는 value 프로퍼티와 1:1 대응하지만 value 어트리뷰트는 초기 상태를, value 프로퍼티는 최신 상태를 가짐
- class 어트리뷰트는 className, classList 프로퍼티와 대응
- for 어트리뷰트는 htmlFor 프로퍼티와 1:1 대응
- td 요소의 colspan 어트리뷰트는 대응하는 프로퍼티가 존재하지 않음
- textContent 프로퍼티는 대응하는 어트리뷰트가 존재하지 않음
- 어트리뷰트 이름은 대소문자를 구별하지 않지만 대응하는 프로퍼티 키는 카멜 케이스를 따름 (maxlength → maxLength)
3-4. DOM 프로퍼티 값의 타입
- getAttribute 메서드로 취득한 어트리뷰트 값은 언제나 문자열이지만 DOM 프로퍼티로 취득한 최신 상태 값은 문자열이 아닐 수 있음
- checkbox 요소의 checked 어트리뷰트 값은 문자열이지만 checked 프로퍼티 값은 불리언 타입
4. data 어트리뷰트와 dataset 프로퍼티
- data 어트리뷰트와 dataset 프로퍼티를 사용하면 HTML 요소에 정의한 사용자 정의 어트리뷰트와 자바스크립트 간에 데이터 교환 가능
- data 어트리뷰트 값은 HTMLElement.dataset 프로퍼티로 취득 가능
- dataset 프로퍼티는 HTML 요소의 모든 data 어트리뷰트의 정보를 제공하는 DOMStringMap 객체 반환
- DOMStringMap 객체는 data 어트리뷰트의 data- 접두사 다음에 붙인 임의의 이름을 카멜 케이스로 변환한 프로퍼티를 가지고 있음
- 이 프로퍼티로 data 어트리뷰트의 값을 취득하거나 변경 가능
<!DOCTYPE html>
<html>
<body>
<ul class="users">
<li id="1" data-user-id="1234" data-role="admin">Echichi</li>
<li id="1" data-user-id="5678" data-role="subscriber">chiyak</li>
</ul>
</body>
<script>
const users = [...document.querySelector(".users").children];
// user-id 가 1234 인 요소 노드 취득
const user = users.find((user) => user.dataset.userId === "1234");
// user-id 가 1234 인 요소 노드에서 data-role 값을 취득
console.log(user.dataset.role); // admin
// user-id가 1234 인 요소 노드에서 data-role 값을 변경
user.dataset.role = "subscriber";
console.log(user.dataset.role); // subscriber
</script>
</html>
스타일
1. 인라인 스타일 조작
- HTMLElement.prototype.style 프로퍼티는 setter과 getter 모두 존재하는 접근자 프로퍼티
- 요소 노드의 인라인 스타일을 취득하거나 추가/ 변경
- style 프로퍼티를 참조하면 CSSStyleDeclration 타입의 객체를 반환
CSSStyleDeclration
- 다양한 CSS 프로퍼티에 대응하는 프로퍼티를 가지고 있으며 이 프로퍼티에 값을 할당하면 해당 CSS 프로퍼티가 인라인 스타일로 HTML 요소에 추가되거나 변경됨
- CSS 프로퍼티는 케밥 케이스를 따르며 CSSStyleDeclration객체의 프로퍼티는 카멜 케이스를 따름
// CSSStyleDeclration 프로퍼티에 값을 할당하면 해당 CSS 프로퍼티가 인라인 스타일로 HTMl 요소에 추가 또는 변경
$div.style.backgroundColor = 'yellow';
// 케밥 케이스의 CSS 프로퍼티를 그대로 사용하려면 객체의 마침표 표기법 대신 대괄호 표기법 사용
$div.style['background-color'] = 'yellow';
2. 클래스 조작
- . 으로 시작하는 클래스 선택자를 사용하여 CSS class를 미리 정한 다음 HTML 요소의 class 어트리뷰트 값을 변경하여 HTML 요소의 스타일 변경 가능
- 이 때 HTML 요소의 class 어트리뷰트를 조작하려면 class 어트리뷰트에 대응하는 요소 노드의 DOM 프로퍼티 사용
- class 어트리뷰트에 대응하는 DOM 프로퍼티는 className 과 classList (자바스크립트에서 class는 예약어)
2-1. className
- Element.prototype.className 프로퍼티는 setter와 getter 모두 존재하는 접근자 프로퍼티
- HTML 요소의 class 어트리뷰트 값을 취득하거나 변경
- 요소 노드의 className 프로퍼티를 참조하면 class 어트리뷰트 값을 문자열로 반환하고 요소 노드의 className 프로퍼티에 문자열을 할당하면 class 어트리뷰트 값을 할당한 문자열로 변경
<!DOCTYPE html>
<html>
<head>
<style>
.box {
width: 100px;
height: 100px;
}
.red {
background-color: red;
}
.yellow {
background-color: yellow;
}
</style>
</head>
<body>
<div class="box red"></div>
</body>
<script>
const $box = document.querySelector(".box");
// .box 요소의 class 어트리뷰트 값을 취득
console.log($box.className); // box red
// .box 요소의 class 어트리뷰트 값 중에서 'red' 만 'yellow'로 변경
$box.className = $box.className.replace("red", "yellow");
</script>
</html>
2-2. classList
- Element.prototype.classList 프로퍼티는 class 어트리뷰트 정보를 담은 DOMTokenList 객체를 반환
<!DOCTYPE html>
<html>
<head>
<style>
.box {
width: 100px;
height: 100px;
}
.red {
background-color: red;
}
.yellow {
background-color: yellow;
}
</style>
</head>
<body>
<div class="box red"></div>
</body>
<script>
const $box = document.querySelector(".box");
// .box 요소의 class 어트리뷰트 정보를 담은 DOMTokenList 객체 취득
// classList 가 반환하는 DOMTokenList 객체는 HTMLCollection과 NodeList와 같이
// 노드 객체의 상태 변화를 실시간으로 반영하는 살아 있는 객체
console.log($box.classList); // DOMTokenList(2) ['box', 'yellow', value: 'box yellow']
// .box 요소의 class 어트리뷰트 값 중에서 'red' 만 'yellow'로 변경
$box.classList.replace("red", "yellow");
</script>
</html>
- DOMTokenList 객체는 class 어트리뷰트의 정보를 나타내는 컬렉션 객체로 유사 배열 객체면서 이터러블
| 메서드 | 설명 |
| add(...className) | 인수로 전달한 1개 이상의 문자열을 class 어트리뷰트 값으로 추가 |
| remove(...className) | 인수로 전달한 1개 이상의 문자열과 일치하는 클래스를 class 어트리뷰트에서 삭제 |
| item(index) | 인수로 전달한 index에 해당하는 클래스를 class 어트리뷰트에서 반환 |
| contains | 인수로 전달한 문자열과 일치하는 클래스가 class 어트리뷰트에 포함되어 있는지 확인 |
| replace(oldClassName, newClassName) | class 어트리뷰트에서 첫 번째 인수로 전달한 문자열을 두 번째 인수로 전달한 문자열로 변경 |
| toggle(className[.force]) | - class 어트리뷰트에 인수로 전달한 문자열과 일치하는 클래스가 존재하면 제거하고 존재하지 않으면 추가 - 두 번째 인수로 불리언 값으로 평가되는 조건식을 전달 가능 (조건식의 평가 결과가 true이면 class 어트리뷰트에 강제로 첫 번째 인수로 전달받은 문자열을 추가하고 false ) |
3. 요소에 적용되어 있는 CSS 스타일 참조
- HTML 요소에 적용되어 있는 모든 CSS 스타일을 참조해야 할 경우 getComputedStyle 메서드 사용
- window.getComputedStyle(element[, pseudo]) 메서드는 첫 번째 인수로 전달한 요소 노드에 적용되어 있는 평가된 스타일을 CSSStyleDeclation 객체에 담아 반환
- 평가된 스타일이란 요소 노드에 적용되어 있는 모든 스타일을 말함
- getComputedStyle 메서드의 두 번째 인수(pseudo)로 :after, :before 와 같은 의사 요소를 지정하는 문자열 전달
'Javascript' 카테고리의 다른 글
| [모던 자바스크립트 Deep Dive] 38. 타이머 (2) | 2023.12.06 |
|---|---|
| [모던 자바스크립트 Deep Dive] 37. 이벤트 (2) | 2023.12.06 |
| [모던 자바스크립트 Deep Dive] 36-2. DOM (0) | 2023.12.02 |
| [모던 자바스크립트 Deep Dive] 36-1. DOM (1) | 2023.12.01 |
| [모던 자바스크립트 Deep Dive] 35. 브라우저의 렌더링 과정 (1) | 2023.11.29 |