feat: example07 작성 완료
This commit is contained in:
12
example07/index.html
Normal file
12
example07/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Simple Component 7</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Example #7</h1>
|
||||
<div id="app"></div>
|
||||
<script src="./src/app.js" type="module"></script>
|
||||
</body>
|
||||
</html>
|
||||
10
example07/src/app.js
Normal file
10
example07/src/app.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import Items from "./components/Items.js";
|
||||
|
||||
class App {
|
||||
constructor() {
|
||||
const $app = document.querySelector('#app');
|
||||
new Items($app);
|
||||
}
|
||||
}
|
||||
|
||||
new App();
|
||||
69
example07/src/components/Items.js
Normal file
69
example07/src/components/Items.js
Normal file
@@ -0,0 +1,69 @@
|
||||
import Component from "../core/Component.js";
|
||||
|
||||
export default class Items extends Component {
|
||||
setup() {
|
||||
this.$state = {
|
||||
items: [
|
||||
{
|
||||
seq: 1,
|
||||
contents: 'item1',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
seq: 2,
|
||||
contents: 'item2',
|
||||
active: true,
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
template() {
|
||||
const {items} = this.$state;
|
||||
return `
|
||||
<ul>
|
||||
${items.map(({contents, active, seq}) => `
|
||||
<li data-seq="${seq}">
|
||||
${contents}
|
||||
<button class="toggleBtn" style="color: ${active ? '#09F' : '#F09'}">
|
||||
${active ? '활성' : '비활성'}
|
||||
</button>
|
||||
<button class="deleteBtn">삭제</button>
|
||||
</li>
|
||||
`).join('')}
|
||||
</ul>
|
||||
<button class="addBtn">추가</button>
|
||||
`
|
||||
}
|
||||
|
||||
setEvent() {
|
||||
this.addEvent('click', '.addBtn', ({target}) => {
|
||||
const {items} = this.$state;
|
||||
const seq = Math.max(0, ...items.map(v => v.seq)) + 1;
|
||||
const contents = `item${seq}`;
|
||||
const active = false;
|
||||
this.setState({
|
||||
items: [
|
||||
...items,
|
||||
{seq, contents, active}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
this.addEvent('click', '.deleteBtn', ({target}) => {
|
||||
const items = [ ...this.$state.items ];;
|
||||
const seq = Number(target.closest('[data-seq]').dataset.seq);
|
||||
items.splice(items.findIndex(v => v.seq === seq), 1);
|
||||
this.setState({items});
|
||||
});
|
||||
|
||||
this.addEvent('click', '.toggleBtn', ({target}) => {
|
||||
const items = [ ...this.$state.items ];
|
||||
const seq = Number(target.closest('[data-seq]').dataset.seq);
|
||||
const index = items.findIndex(v => v.seq === seq);
|
||||
items[index].active = !items[index].active;
|
||||
this.setState({items});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
28
example07/src/core/Component.js
Normal file
28
example07/src/core/Component.js
Normal file
@@ -0,0 +1,28 @@
|
||||
export default class Component {
|
||||
$target;
|
||||
$state;
|
||||
constructor ($target) {
|
||||
this.$target = $target;
|
||||
this.setup();
|
||||
this.setEvent();
|
||||
this.render();
|
||||
}
|
||||
setup () {};
|
||||
template () { return ''; }
|
||||
render () {
|
||||
this.$target.innerHTML = this.template();
|
||||
}
|
||||
setEvent () {}
|
||||
setState (newState) {
|
||||
this.$state = { ...this.$state, ...newState };
|
||||
this.render();
|
||||
}
|
||||
addEvent (eventType, selector, callback) {
|
||||
const children = [ ...this.$target.querySelectorAll(selector) ];
|
||||
const isTarget = (target) => children.includes(target) || target.closest(selector);
|
||||
this.$target.addEventListener(eventType, event => {
|
||||
if (!isTarget(event.target)) return false;
|
||||
callback(event);
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user