-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
147 lines (131 loc) · 3.36 KB
/
index.html
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h3>Example 1</h3>
<details>
<summary>상태를 가진 컴포넌트 구현</summary>
<ol>
<li>버튼 클릭시마다 setState를 호출하여 리스트에 아이템 추가.</li>
<li>setState에서 render 함수 호출해 리렌더링 수행.</li>
<li>클래스 문법을 통해 추상화</li>
</ol>
<div id="state"></div>
<div id="app"></div>
</details>
<hr />
<h3>Example 2</h3>
<details>
<summary>클래스 문법 통해 추상화</summary>
<ol>
<li>컴포넌트 생성 방법 강제.</li>
</ol>
<div id="state2"></div>
<div id="app2"></div>
</details>
<hr />
<h3>Example 3</h3>
<details>
<summary>모듈화</summary>
<div id="app3"></div>
</details>
<script src="./src/app.js" type="module"></script>
<script>
const initialItems = ['item1', 'item2', 'item3']
let state = {
items: initialItems
}
/*
* render: 현재 상태값 기반으로 아이템 리스트와 아이템 추가 버튼을 화면에 렌더링.
**/
const render = () => {
const { items } = state;
document.querySelector('#state').innerHTML = `
current state: ${JSON.stringify(state)}
`
document.querySelector('#app').innerHTML = `
<ul >
${items.map((item) => `<li>${item}</li>`).join('')}
</ul >
<button id='append'>Append Item</button>
`
document.querySelector('#append').addEventListener('click', () => {
setState({ items: [...items, `item${items.length + 1}`] })
})
}
/*
* setState: 신규 상태값으로 상태를 변경하고, render 함수 호출해 리렌더링.
* @newState object
**/
const setState = (newState) => {
state = { ...state, ...newState };
render();
}
render();
/*
* CustomComponent : 추상화 통해 컴포넌트 사용 방법 강제.
**/
class CustomComponent {
target;
state;
constructor(target) {
this.target = target;
this.initialStateSetup();
this.render();
}
/*
* initialSetup : 초기 상태값 설정.
**/
initialStateSetup() { };
/*
* getChild : 초기 컴포넌트 내부에 들어갈 child Components 문바열 형태로 반환.
**/
getChild() { return ''; }
/*
* render : 컴포넌트 렌더링해 화면에 표시.
**/
render() {
this.target.innerHTML = this.getChild();
this.setEventListener();
}
/*
* setEventListener : 컴포넌트에 이벤트 리스너 추가.
**/
setEventListener() { }
/*
* setState : 컴포넌트 내부 상태 변경.
**/
setState(newState) {
this.state = { ...this.state, ...newState };
this.render();
}
}
class App extends CustomComponent {
initialStateSetup() {
this.state = { items: initialItems };
}
getChild() {
const { items } = this.state;
return `
<ul>
${items.map(item => `<li>${item}</li>`).join('')}
</ul>
<button id='append'>Item 추가</button>
`
}
setEventListener() {
this.target.querySelector('button').addEventListener('click', () => {
const { items } = this.state;
this.setState({ items: [...items, `item${items.length + 1}`] });
});
}
}
new App(document.querySelector('#app2'));
</script>
</body>
</html>