export class Component {
constructor(hostElementId, insertBefore = false) {
if (hostElementId) {
this.hostElement = document.getElementById(hostElementId);
} else {
this.hostElement = document.body;
}
this.insertBefore = insertBefore;
}
detach() {
if (this.element) {
this.element.remove();
// this.element.parentElement.removeChild(this.element);
}
}
attach() {
this.hostElement.insertAdjacentElement(
this.insertBefore ? "afterbegin" : "beforeend",
this.element
);
}
}
exports : 이 모듈 안에 있는 해당 클래스를 다른 파일에도 사용할 것이다.<script src="assets/scripts/app.js" defer type="module"></script>
type="module"키워드를 이해하고 모든 스크립트가 이 스크립트를 참조로 한다고 알려준다.따라서 모든 코드를 모듈화하면 다음과 같다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Project Board</title>
<link rel="stylesheet" href="assets/styles/app.css" />
<!-- <script src="assets/scripts/Utility/DOMHelper.js" defer></script> -->
<!-- <script src="assets/scripts/App/Component.js" defer></script> -->
<!-- <script src="assets/scripts/App/Tooltip.js" defer type="module"></script>
<script src="assets/scripts/App/ProjectItem.js" defer></script>
<script src="assets/scripts/App/ProjectList.js" defer></script> -->
<script src="assets/scripts/app.js" defer type="module"></script>
</head>
<body>
<template id="tooltip">
<h2>More Info</h2>
<p></p>
</template>
<header id="main-header">
<h1>Project Planner</h1>
</header>
<section id="active-projects">
<header>
<h2>Active Projects</h2>
</header>
<ul>
<li
id="p1"
data-extra-info="Got lifetime access, but would be nice to finish it soon!"
class="card"
draggable="true"
>
<h2>Finish the Course</h2>
<p>Finish the course within the next two weeks.</p>
<button class="alt">More Info</button>
<button>Finish</button>
</li>
<li
id="p2"
data-extra-info="Not really a business topic but still important."
class="card"
draggable="true"
>
<h2>Buy Groceries</h2>
<p>Don't forget to pick up groceries today.</p>
<button class="alt">More Info</button>
<button>Finish</button>
</li>
</ul>
</section>
<section id="finished-projects">
<header>
<h2>Finished Projects</h2>
</header>
<ul>
<li
id="p3"
data-extra-info="Super important conference! Fictional but still!"
class="card"
draggable="true"
>
<h2>Book Hotel</h2>
<p>
Academind conference takes place in December, don't forget to book a
hotel.
</p>
<button class="alt">More Info</button>
<button>Activate</button>
</li>
</ul>
</section>
<footer>
<button id="stop-analytics-btn">Stop Analytics</button>
</footer>
</body>
</html>
import { ProjectList } from "./App/ProjectList.js";
// App 코드
App 폴더
export class Component {}
import { DOMHelper } from "../Utility/DOMHelper.js";
import { Tooltip } from "./Tooltip.js";
// ProjectItem 코드
export class ProjectItem {}
import { ProjectItem } from "./ProjectItem.js";
import { DOMHelper } from "../Utility/DOMHelper.js";
// ProjectList 코드
export class ProjectList {}
import { Component } from "./Component.js";
// Component 코드
export class Tooltip extends Component {}
Utility 폴더
export class DOMHelper {}
export class DOMHelper {
static clearEventListeners(element) {
const clonedElement = element.cloneNode(true);
element.replaceWith(clonedElement);
return clonedElement;
}
static moveElement(elementId, newDestinationSelector) {
const element = document.getElementById(elementId);
const destinationElement = document.querySelector(newDestinationSelector);
destinationElement.append(element);
element.scrollIntoView({ behavior: "smooth" });
}
}
export function clearEventListeners(element) {
const clonedElement = element.cloneNode(true);
element.replaceWith(clonedElement);
return clonedElement;
}
export function moveElement(elementId, newDestinationSelector) {
const element = document.getElementById(elementId);
const destinationElement = document.querySelector(newDestinationSelector);
destinationElement.append(element);
element.scrollIntoView({ behavior: "smooth" });
}
import {
moveElement,
DOMHelper,
clearEventListener,
} from "../Utility/DOMHelper.js";
// 혹은
import * as DOMHelper from "../Utility/DOMHelper.js"; // 해당 파일의 모든 export 문을 번들로 묶어서 DOMHelper로 사용하겠다.
export function doSomething() {}
export default class {}
import Cmp, { doSomething } from "./Component.js";
export class Tooltip extends Cmp {}
많은 모듈을 임포트 하는 것은 적절하지 않다. 따라서 동적 가져오기(코드가 항상 필요한 것이 아니라 조건부로!)를 이용할 수 있다.
import("./Tooltip.js").then((module) => {
const tooltip = new module.Tooltip(
() => {
this.hasActiveTooltip = false;
},
tooltipText,
this.id
);
tooltip.attach();
this.hasActiveTooltip = true;
});
모듈 안의 코드는 모듈이 처음으로 임포트 및 로드될 때만 실행된다. 처음에만 실행된다는 점이 중요!
여러 번 임포트하는 모듈이 있어도 딱 한번만 console.log()가 실행된다. → 처음 임포트 될 때에만 실행. 이것은 동적 임포트에도 적용이 됨.
import { DOMHelper } from "../Utility/DOMHelper.js";
console.log("Project Item Created"); // 해당 코드는 export 되지 않아도 실행되었음을 알 수 있다.
export class ProjectItem {}
const DEFAULT_VALUE = 'Taemin';
console.log(window) // window 객체 출력
console.log(DEFAULT_VALUE) // 오류 발생!
DEFAULT_VALUE는 전역 객체에 노출되지 않음을 알 수 있다.window는 일종의 전역 변수임에도 여전히 출력// 다음과 같이 정의하면 전역 객체로!
// app.js
window.DEFAULT_VALUE = 'Taemin';
// ProjectList.js
console.log(window.DEFAULT_VALUE) // Taemin
console.log() 문장을 app.js에서 전역객체로 선언한 것 보다 더 늦게 수행되도록 connectDroppable() 함수 안에 넣으면 위의 결과를 확인할 수 있다.globalThisglobalThis.DEFAULT_VALUE = 'Taemin';
🔗 module