🔷 프로그램을 구성하는 구성 요소로, 관련된 데이터와 함수를 하나로 묶은 단위
import
장점
💡 import를 사용하려면 웹 서버가 필요한데 serve 모듈로 로컬 웹 서버를 띄워서 진행하기 때문에 우린 상관없다.
🖥 모듈 사용법
// module-name 내에 export default로 내보내진 것을 가져온다
import defaultExport from "module-name";
// module-name 내에서 export된 모든 것을 모두 가져온다. as 이후 이름은 중복되지만 않으면 자유롭게 정할 수 있다.
import * as allItems from "module-name";
// module-name 내에서 export 된 것 중에 특정 값만 가져온다.
import {loadItem} from "module-name";
// module-name 내에서 export 된 것 중에 특정 값만 이름을 바꿔서 가져온다.
import {
loadItem as loadSomething
} from "module-name";
// export default된 것과 개별 export 된 것을 한번에 가져올 수도 있다.
import defaultFunction, {
loadItem
} from "module-name";
// 별도의 모듈 바인딩이 없이 불러오기
import "module.name"
❗ from 이후 모듈 이름 맨 뒤에 .js 잘 붙였는지 확인할 것
🖥 모듈 예시(App.js)
export default function App () {
this.render = () => {
alert('hello!')
}
this.render()
}
export const printToday = () => {
console.log(new Date().toLocaleString()) // 지역에 맞는 날짜 표기법으로 바꿔서 출력
}
🖥 constants.js
export const DOMAIN_NAME = 'www.naver.com'
export const PORT = '8000'
export const isProduction = () => {
return false
}
🖥 index.js
// import문은 항상 맨 위!
import * as constants from './constants.js'
import App from './App.js'
const $body = document.querySelector('body')
$body.innerHTML = $body.innerHTML + JSON.stringify(constants)
new App()
🖥 index.html
<!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>
<script src = "./src/index.js" type="module"></script> <!--type="module" 추가-->
</body>
</html>
🖨 출력 결과
🖥 index.html
<!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>simple Todo List</title>
</head>
<body>
<main class="app"></main>
<script src="./src/main.js" type="module"></script> <!--type 추가 후 나머지 컴포넌트 호출 삭제-->
</body>
</html>
🖥 App.js
// App에서 사용하는 컴포넌트, 함수를 import 키워드를 불러오도록 선언
import Header from './Header.js'
import TodoForm from './TodoForm.js'
import TodoList from './TodoList.js'
import { setItem } from './storage.js'
export default function App({$target, initialState}) {
new Header({
$target,
text: 'simple Todo List'
})
new TodoForm({
$target,
onSubmit: (text) => {
const nextState = [...todoList.state, { text }]
todoList.setState(nextState)
setItem('todos', JSON.stringify(nextState)) // storage 부분 삭제
}
})
const todoList = new TodoList ({
$target,
initialState
})
}
🖥 storage.js
const storage = window.localStorage
export const setItem = (key, value) => {
try {
storage.setItem(key,value)
} catch(e) {
console.log(e)
}
}
export const getItem = (key, defaultValue) => {
try {
const storedValue = storage.getItem(key)
if(storedValue) {
return JSON.parse(storedValue)
}
return defaultValue
} catch(e) {
console.log(e)
return defaultValue
}
}
// 모듈식으로 필요할 때만 꺼내는 방식으로 수정
🖥 Header.js
export default function Header ({$target, text}) {
const $header = document.createElement('h1')
$target.appendChild($header)
this.render = () => {
$header.textContent = text
}
this.render()
}
🖥 TodoList.js
export default function TodoList({$target, initialState}) {
const $todoList = document.createElement('div'); // 컴포넌트의 DOM
$target.appendChild($todoList);
this.state = initialState;
// 현재의 상태를 변경하고 변경한 상태를 다시 랜더링
this.setState = nextState => {
this.state = nextState;
this.render();
}
this.render = () => {
$todoList.innerHTML = `
<ul>
${this.state.map(({text}) =>`<li>${text}</li>`).join('')}
</ul>
`
}
this.render();
}
🖥 TodoForm.js
export default function TodoForm({$target, onSubmit}) {
const $form = document.createElement('form')
$target.appendChild($form)
let isInit = false;
this.render = () => {
$form.innerHTML = `
<input type ="text" name = "todo" />
<button>add</button>
`
if(!isInit) {
$form.addEventListener('submit', e => {
e.preventDefault();
const $todo = $form.querySelector('input[name=todo]')
const text = $todo.value
if(text.length > 1) { // 한 글자 이상 들어왔을 때만 (없으면 빈 문자열만 들어갈 수 있음)
$todo.value = '' // 입력 후 input 비워주기
onSubmit(text) // App.js의 TodoForm 내의 onSubmit이 호출
}
})
isInit = true
}
}
this.render()
}
// module
// TodoForm, TodoList, Header 컴포넌트는 외부 의존성이 없기 때문에 export default로 사용
🖥 main.js
import App from './App.js'
import { getItem } from './storage.js'
const initialState = getItem('todos', [])
const $app = document.querySelector('.app')
new App({
$target: $app,
initialState
})
🖨 출력 결과
잘 돌아간다.
다음 시간엔 아주 중요한... 비동기처리와 promise, async, await를 다룰 것이다.