GetShitDone-2
๐จ ํ๋ก์ ํธ ์ผ์ง
์ ๋ณด ์ ๋ฌ๋ณด๋จ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉฐ ๊ฒช์ ์ ๋ค, ๋๋ ์ ๋ค์ ๊ธฐ๋กํ ์ผ์ง
Project
: Get Shit Done
๋๋ง์ ToDo๋ฆฌ์คํธ๋ฅผ ๋ง๋ค๊ธฐ ์ํด ์์ํ ํ๋ก์ ํธ
Get Shit Done
์ ๊ทธ๋ฅ ๋ฅ์น๊ณ ํด
๋ผ๋ ์๋ฏธ๋ก ํ์์ ์ค์ค๋ก ๋ค์งํ๋ ๋ฌธ์ฅ์ธ๋ฐ, ํฌ๋๋ฆฌ์คํธ์ ์ด์ธ๋ฆฐ๋ค ์๊ฐํ์ฌ ํ๋ก์ ํธ๋ช
์ผ๋ก ์ ํ๊ฒ ๋์๋ค.
์ด๋ฒ ํ๋ก์ ํธ์ ๊ฐ์ฅ ํฐ ๋ชฉ์ ๊ณผ ์์๋ ์นํฉ ๋ฐ ๋ฐ๋ฒจ์ ํตํด ๊ฐ ๋ชจ๋์ ์น ์ปดํฌ๋ํธ
๋ก ๊ตฌ์ฑํ์ฌ ๋์ํ๊ฒ ํ๋ ๊ฒ์ด๋ค!!!
๐คช ์ปดํฌ๋ํธ ๋ก์ง
๋จผ์ ๋ค์ด๊ฐ๊ธฐ์ ์์ ์ปดํฌ๋ํธ๋ฅผ ๋๋ ๋ถ๋ถ์ ๋ค์ ๋ณด์๋ฉด, ํฌ๊ฒ ์๋์ ๊ฐ์ด ๋๋์๋ค.
- todoApp.js: ์ ์ฒด ์ฑ์ ๋ํ๋ธ๋ค.
- todoContainer.js: ์ฑ ๋ด์ ๋ฉ๋ชจ์ฅ์ ๋ํ๋ธ๋ค.(์ฌ๋ฌ๊ฐ์ ๋ฉ๋ชจ์ฅ์ ์์ฑํ๊ฒ ํ ์์ )
- todoToolbar.js: ๋ฉ๋ชจ์ ๋ํ ์กฐ์์ ํ๋ ํด๋ฐ ๋ถ๋ถ
- todoNote.js: ํด๋ฐ ์กฐ์์ ๋ฐ๋ผ ๋ฉ๋ชจ๋ฅผ ์ ๋ ฅํ ์ ์๋ input ๋ถ๋ถ
- todoList.js: ๋ฉ๋ชจ ์ ์ฒด๋ฅผ ๊ฐ์ธ๊ณ ์๋ ๋ถ๋ถ
- todoItem.js: ๋ฉ๋ชจ ์ปดํฌ๋ํธ
์ง๊ธ ๋ค์ ์๊ฐํด๋ณด๋ฉด todoItem์ ๋ด์๋ todoList๋ ๋ฐ๋ก ์ปดํฌ๋ํธํ ์ํด๋ ๋์ง ์์์๊น ์ถ๋ค.(์ด๋ฐ ๊ฒ ๋ค ๋ฐฐ์ฐ๋ ๊ฑฐ๋๊น ๐คช)
๐งญ todoApp
์ฌ๊ธฐ์ ์ฒ์์ ํฌ๊ฒ ์ปจํ
์ด๋ ์์ฑ
๋ฒํผ์ ๋๊ณ ํด๋ฆญ์ ๋ฉ๋ชจ์ฅ์ ๋ง๋ค์ด์ง๋ ์์ผ๋ก ๊ตฌ์ฑํ์๋ค.
์คํ์ผ๋ง๊น์ง ๋ค๋ฃจ๊ธฐ์ ์์ด ๋๋ฌด ๋ง์ผ๋ฏ๋ก ํจ์คํ๊ณ ์ ๋ฐ์ ์ธ ์ฝ๋ ๊ตฌ์กฐ๋ง ๋ณด์๋ฉด ์๋์ ๊ฐ๋ค.
<header class="header">
<span>Just Do it!</span>
<span class="header__menu">Menu</span>
</header>
<main class="main">
<div class="create-container-button">+ Add Container</div>
</main>
connectedCallback() {
// 1. create-container-button ํด๋ฆญ ์ ์ปจํ
์ด๋ ์์ฑ
const $createContainerButton = this.shadowRoot.querySelector(
'.create-container-button'
);
const $appMain = this.shadowRoot.querySelector('.main');
$createContainerButton.addEventListener('click', (event) => {
const containerTitleInput = prompt(
'๐ฅ (๋์ด์ฐ๊ธฐ ์์ด)๋ฉ๋ชจ์ฅ ์ด๋ฆ์ ์ ์ด์ฃผ์ธ์.'
)
.split(' ')
.join('');
if (!containerTitleInput) return;
const $newContainer = document.createElement('todo-container');
$newContainer.dataset.containerTitle = containerTitleInput;
// ์ถํ ๋ง๋ค todo-container ํ๊ทธ๋ฅผ ๋ฃ์ด์ค๋ค
$appMain.insertBefore($newContainer, $createContainerButton);
// 1-1. ๋ฉ๋ชจ ์ปจํ
์ด๋ 5๊ฐ ์ด์ ์, Add column ์ญ์
if ($appMain.children.length >= 6) {
$createContainerButton.style.display = 'none';
}
});
}
์์ ๊ฐ์ด + Add container
๋ฅผ ๋๋ฅด๋ฉด ๋ฉ๋ชจ์ฅ ์ด๋ฆ์ ๋ฌผ์ด๋ณด๋ ๋ชจ๋ฌ ์ฐฝ์ด ๋์ค๊ณ ๋ฉ๋ชจ์ฅ์ด ๋ง๋ค์ด์ง๋ค.
๐งญ todoContainer
์ฌ๊ธฐ์๋ ํฌ๊ฒ ๋ณต์กํ ๋ก์ง์ ์๊ณ App์์ ๋ฐ์ ๋ฐ์ดํฐ ํ์ดํ์ ๊ฐ ์ปจํ ์ด๋ ๋ด๋ถ ์์๋ค์ dataset์ผ๋ก ์ ๋ฌํด์ฃผ์๋ค.(์ถํ ๊ฐ ๋ฉ๋ชจ์ฅ ๋ณ ๊ฐ์ ๊ตฌ๋ถํ๊ธฐ ์ํจ)
connectedCallback() {
const containerTitle = this.dataset.containerTitle;
const $toolBar = this.shadowRoot.querySelector('.todo-toolbar');
$toolBar.dataset.containerTitle = containerTitle;
const $note = this.shadowRoot.querySelector('.todo-note');
$note.dataset.containerTitle = containerTitle;
}
๐งญ todoToolbar
๋ฉ๋ชจ์ฅ์ ์กฐ์ํ๊ธฐ ์ํ ๊ฐ๋จํ ํด๋ฐ
connectedCallback() {
// 1. ํด๋ฐ + ๋ฒํผ ํด๋ฆญ ์, note ์ด๊ธฐ/๋ซ๊ธฐ
const $openNoteButton = this.shadowRoot.querySelector('.open-note-button');
const $todoNote = this.nextElementSibling;
$openNoteButton.addEventListener('click', (event) => {
if ($todoNote.style.display === 'none') {
$todoNote.style.display = 'flex';
} else {
$todoNote.style.display = 'none';
}
});
// 2. X ๋ฒํผ ํด๋ฆญ ์, container ์ญ์
const $deleteContainerButton = this.shadowRoot.querySelector(
'.delete-container-button'
);
$deleteContainerButton.addEventListener('click', (event) => {
if (!confirm('์ ๋ง ์ญ์ ํ์๊ฒ ์ต๋๊น?')) return;
const containerTitle = this.dataset.containerTitle;
const $todoApp = document.querySelector('todo-app');
const $containerSelected = $todoApp.shadowRoot.querySelector(
`[
data-container-title=${containerTitle}
]`
);
console.log($containerSelected);
$containerSelected.remove();
// 2-1. ์ปจํ
์ด๋ 5๊ฐ ๋ฏธ๋ง์ผ ๋, add column ์ฌ์์ฑ
const $appMain = $todoApp.shadowRoot.querySelector('.main');
const $createContainerButton = $appMain.querySelector(
'.create-container-button'
);
if ($createContainerButton.style.display === 'none') {
$createContainerButton.style.display = 'block';
}
});
// 3. add column ํด๋ฆญ ์ ์
๋ ฅ๊ฐ์ name์ผ๋ก ๊ฐ๋ container ์์ฑ
const $containerName = this.shadowRoot.querySelector('.container-name');
$containerName.textContent = this.dataset.containerTitle;
}
2๋ฒ container๋ฅผ ์ง์ฐ๋ ๋ถ๋ถ์ ์ถํ์ ๋ฆฌํฉํ ๋งํ ์์ ์ด๋ค. shadow DOM์ด ๊ฐ๊ฐ์ DOM์ ๊ฐ๊ฐ์ ์ปดํฌ๋ํธ๋ก ์กด์ฌํ๊ฒ ํด์ฃผ์ด ๋ ๋ฆฝ์ ์ผ๋ก ์คํ์ผ ์ ์ฉ์ด ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ ์ข์๋ค. ํ๋ฐ, ๋ง ๊ทธ๋๋ก ์ปดํฌ๋ํธ ํ๋ํ๋๊ฐ ๋ ๋ฆฝ์ ์ธ ๊ฐ์ฒด(OOP ๊ด์ ์์)๋ก ์กด์ฌํ๋ค๋ณด๋ ํ๋์ html ๊ตฌ์กฐ๋ก ๋์ด์์ ๋์ฒ๋ผ Node api๋ฅผ ํตํ ์ ๊ทผ์ด ๋ถ๊ฐ๋ฅํ๋ค๋ ์ ์ด ๋ถํธํ๋ค. ๊ฐ๊ฐ์ Shadow DOM์ root node๊ฐ ๊ณง ๊ทธ ๋ชจ๋์ ํ๊ทธ ์ฆ, custom element์ด๋ค๋ณด๋ ๊ทธ ์๋ก ์ ๊ทผํ๊ธฐ ์ํด dataset์ ์ด์ฉํ์ฌ ์์์๋ถํฐ document๋ก ์ ๊ทผํด์ผํ๋ค. ์ด๋ ๊ฒ ์ ๊ทผํ๋ ๊ฒ ๋ญ๊ฐ ๊น๋ํ ๋ฐฉ๋ฒ์ ์๋๋ผ, ์ถํ์ ์ข๋ ์ฐพ์๋ด์ผํ ๊ฒ ๊ฐ๋ค.
3ํธ์์ ๊ณ์โฆ