0%

201229_TIL(DOM_2)

오늘 배운 것

DOM

data 어트리뷰트와 dataset 프로퍼티

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<body>
<ul class="todos">
<li id="1" data-user-id="1">HTML</li>
<li id="2" data-user-id="2">CSS</li>
<li id="2" data-user-id="3">JS</li>
</ul>
<script>
document.querySelector(".todos > li").dataset.customerId = "0"; // 해당 어트리뷰트가 없으면 생성한다.
console.log(document.querySelector(".todos > li").dataset.userId); // 1
</script>
</body>
</html>

스타일

인라인 스타일 조작

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<body>
<ul class="todos">
<li id="1">HTML</li>
<li id="2">CSS</li>
<li id="2">JS</li>
</ul>
<script>
document.querySelector(".todos > li").style.color = "red";
</script>
</body>
</html>

클래스 조작

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html>
<head>
<style>
.red {
color: red;
}
.big {
font-size: 10em;
}
</style>
</head>
<body>
<ul class="todos">
<li id="1">HTML</li>
<li id="2">CSS</li>
<li id="2">JS</li>
</ul>
<script>
document.querySelector(".todos > li").className = "red big";
</script>
</body>
</html>

className은 문자열로 class를 보관하기 때문에 유사배열 객체로 구성된 classList가 사용하기 더 편리하다. classList는 메서드도 제공한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html>
<head>
<style>
.red {
color: red;
}
.big {
font-size: 10em;
}
.small {
font-size: 1em;
}
</style>
</head>
<body>
<ul class="todos">
<li id="1">HTML</li>
<li id="2">CSS</li>
<li id="2">JS</li>
</ul>
<script>
document.getElementById("1").classList.add("red", "big"); // red big 적용
document.getElementById("1").classList.remove("red"); // big 적용
document.getElementById("1").classList.contains("big"); // ture (적용 여부)
document.getElementById("1").classList.replace("big", "small"); // small (교체)
document.getElementById("1").classList.toggle("red"); // small red (없으면 추가)
document.getElementById("1").classList.toggle("red"); // small (있으면 삭제)
</script>
</body>
</html>

요소에 적용되어 있는 CSS 스타일 참조

style 프로퍼티는 인라인 스타일만 반환한다. 따라서 클래스를 적용한 스타일이나 상속을 통해 암묵적으로 적용된 스타일은 style 프로퍼티로 참조할 수 없다. HTML 요소에 적용되어 있는 모든 CSS 스타일을 참조해야 할 경우 getComputedStyle 메서드를 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html>
<head>
<style>
body {
color: red;
}
.box {
width: 100px;
height: 50px;
background-color: cornsilk;
border: 1px solid black;
}
</style>
</head>
<body>
<div class="box">Box</div>
<script>
const $box = document.querySelector(".box");

// .box 요소에 적용된 모든 CSS 스타일을 담고 있는 CSSStyleDeclaration 객체를 취득
const computedStyle = window.getComputedStyle($box);
console.log(computedStyle); // CSSStyleDeclaration

// 임베딩 스타일
console.log(computedStyle.width); // 100px
console.log(computedStyle.height); // 50px
console.log(computedStyle.backgroundColor); // rgb(255, 248, 220)
console.log(computedStyle.border); // 1px solid rgb(0, 0, 0)

// 상속 스타일(body -> .box)
console.log(computedStyle.color); // rgb(255, 0, 0)

// 기본 스타일
console.log(computedStyle.display); // block
</script>
</body>
</html>

getComputedStyle 메서드의 두 번째 인수(pseudo)로 :after, :before와 같은 의사 요소 를 지정하는 문자열을 전달할 수 있다. 의사 요소가 아닌 일반 요소의 경우 두 번째 인수는 생략한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>
<head>
<style>
.box:before {
content: "Hello";
}
</style>
</head>
<body>
<div class="box">Box</div>
<script>
const $box = document.querySelector(".box");

// 의사 요소 :before의 스타일을 취득한다.
const computedStyle = window.getComputedStyle($box, ":before");
console.log(computedStyle.content); // "Hello"
</script>
</body>
</html>

이벤트

이벤트 드리븐 프로그래밍

이벤트가 발생했을 때 호출될 함수를 이벤트 핸들러(event handler)라 하고, 이벤트가 발생했을 때 브라우저에게 이벤트 핸들러의 호출을 위임하는 것을 이벤트 핸들러 등록이라 한다. 프로그램의 흐름을 이벤트 중심으로 제어하는 프로그래밍 방식을 **이벤트 드리븐 프로그래밍(event-driven programming)**이라 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button>Hello</button>
<script>
document.querySelector("button").onclick = () => {
console.log("Hello");
};
</script>
</body>
</html>

이벤트 핸들러 등록

이벤트 핸들러 어트리뷰트 방식

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<body>
<button onclick="sayHi('Lee')">Click me!</button>
<!-- <button onclick="console.log(`Hi!`);">Click me!</button -->
<script>
function sayHi(name) {
console.log(`Hi! ${name}.`);
}
</script>
</body>
</html>
이벤트 핸들러 어트리뷰트 값으로 함수 참조가 아닌 인수 전달을 위힌 함수 호출문 등의 문을 할당한다. onclick 어트리뷰트 값은 onclick이란 함수 이름을 가진 함수 몸체 안에 들어오는 문들을 넣어주는 것과 마찬가지다.

이벤트 핸들러 프로퍼티 방식

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input id="username" type="text" placeholder="username">
<span class="display"></span>
<script>
const $username = document.getElementById('username');
const $display = document.querySelector('.display');

$username.oninput = () => {
$display.textContent = $username.value;
};
</script>
</body>
</html>

todoList 간단하게 만들어보기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>

<body>
<form>
<input class="input-todo" type="text" placeholder="enter todo!" />
<!-- 버튼 타입을 버튼으로 지정하지 않으면 submit이 기본값 -->
<button class="add">Add</button>
</form>

<ul class="todos"></ul>

<script>
const $form = document.querySelector("form");
const $inputTodo = document.querySelector(".input-todo");
// const $add = document.querySelector('.add'); // submit 버튼을 add로 대체
const $todos = document.querySelector(".todos");

const addTodo = () => {
const { value } = $inputTodo;
if (!value) return;

// $todos.innerHTML += `<li>${value}</li>`;
const $li = document.createElement("li");
const $checkbox = document.createElement("input");
const $span = document.createElement("span");
const $remove = document.createElement("button");

$checkbox.setAttribute("type", "checkbox");
$span.textContent = value;
$remove.classList.add("remove");
$remove.textContent = "X";

$li.appendChild($checkbox);
$li.appendChild($span);
$li.appendChild($remove);
$todos.appendChild($li);

$inputTodo.value = "";
$inputTodo.focus();
};

// $add.onclick = addTodo;

// $inputTodo.onkeyup = e => {
// if (e.key !== 'Enter') return;
// addTodo();
// };

$form.onsubmit = (e) => {
e.preventDefault();
addTodo();
};
</script>
</body>
</html>

Nyong’s GitHub