1. PageComponent의 역할
PageComponent는 index.html
의 body
의 콘텐츠가 포함될 main
에 삽입될 ul
태그를 동적으로 생성하는 class 다.
이 class 를 이용하면, class=page
속성을 가진 ul
태그가 생성되고, 생성된 태그가 attachTo(parent, position)
라는 메서드를 통해 정해진 위치로 삽입된다.
constructor
는 이 class의 instance가 생성됨과 동시에 실행되는데 (new PageComponent
가 될 때) element
라는 변수가 html tag로 변환되는 과정이 담겨 있다. createElement, setAttribute, textContent
를 통해서 각각 ul
태그 생성, 속성 부여, text 삽입이 된다.
// pate.ts
class PageComponent {
// 이 컴포넌트에서의 element를 정의
// 타입은 Typescript 에 내장되어 있는 DOM type으로 정의
// 정의된 element는 은닉을 위해 private 접근제한자를 설정
private element: HTMLUListElement;
//
constructor() {
// element는 ul tag 이고,
// class="page" 로 attribute가 설정
this.element = document.createElement("ul");
this.element.setAttribute("class", "page");
this.element.textContent = "This is page component";
// method를 정의
// attachTo 는 부모 node를 파라미터로 받아, 그 부모를 기준으로 지정된 위치에
// this.element를 삽입하는 method 이다
// insertAdjacentElement는 DOM node를 지정된 위치에 insert 해주는 DOM api 이다
attachTo(parent: HTMLElement, position: InsertPosition = "afterbegin") {
parent.insertAdjacentElement(position, this.element)
}
}
}
2. ImageComponenet의 역할
class ImageComponent {
private element: HTMLElement;
contructor(title: string, url: string) {
// template 라는 html tag는 페이지가 로드될 때 숨겨질 컨텐츠를 보관하고
// js를 통해서 표시할 수 있다. 즉 처음에는 render가 되지 않다가 js를 통해 어떤
// 명령이 실행되면 그것이 렌더링 되도록 구현 할 수 있다.
// template tag 생성
const template = document.createElement("template");
// <template></template> 안에 넣을 요소들을 삽입
template.innerHTML = `
<section class="image">
<div class="image__holder">
<img class="image__thumbnail">
<p class="image__title"></p>
</div>
</section>`
// element를 teamplate 안 요소들중 첫 자식 tag (section)으로 initialize 한다.
// as HTMLElement 와 같이 type assertion 이 필요한 이유 👇
// firstElementChild 의 type이 Element | null 이지만 확정적으로 '나'는 이것의 타입이 HTMLElement 임을 알기 때문에 assertion을 해준다.
this.element = template.content.firstElementChild as HTMLElement;
// 그리고, 그 안에서 <img> 태그를 추출하여, 동적으로 src 와 alt 를 설정한다.
const imageElement = this.element.querySelector(".image__thunmbnail")! as HTMLImageElement;
// attribute set
imageElement.alt = title;
imageElement.src = url;
const titleElement = this.element.querySelector(".image__title")! as HTMLParagrapahElement;
// textContent set
titleElement.textContent = title;
}
// method를 정의
// attachTo 는 부모 node를 파라미터로 받아, 그 부모를 기준으로 지정된 위치에
// this.element를 삽입하는 method 이다
// insertAdjacentElement는 DOM node를 지정된 위치에 insert 해주는 DOM api 이다
attachTo(parent: HTMLElement, position: InsertPosition = "afterbegin") {
parent.insertAdjacentElement(position, this.element);
}
}
3. app.ts 에서 컴포넌트(PageComponent, ImageComponent) 사용하기
// app.ts
// 생성한 class 를 import 한다.
import { ImageComponent } from "./page/item/image.js";
import { PageCoponents } from "./page/page.js";
class App {
private readonly page: PageComponent;
constructor(appRoot: HTMLElement){
// PageComponent의 instance를 생성한다.
this.page = new PageComponent();
this.page.attachTo(appRoot);
// IamgeComponent의 instance를 생성한다.
const image = new ImageComponent(
"사진입니다",
"https:///picsum.photos/600/300"
);
image.attachTo(appRoot, "beforeend")
}
}
4. 결과
<!-- index.htmk -->
<body>
<div class="app">
<header class="banner">
<h1 class="banner__title">Motion</h1>
<ul class="panel">
<li> <button id="new-image" class="panel-button">이미지</button></li>
<li> <button id="new-video" class="panel-button">비디오</button></li>
<li> <button id="new-note" class="panel-button">노트</button></li>
<li> <button id="new-todo" class="panel-button">할일</button></li>
</ul>
</header>
<main class="document">
<!-- template가 class에서 생성됨 -->
</main>
<footer class="footer">
<p>copyright by With, All right reserved</p>
</footer>
</div>
</body>
View