객체지향 프로그래밍

Web API

우리가 사용하는 대부분의 Web API는 객체지향적으로 설계되어 있다.

Standards — WHATWG

7.1 Setting 앱 만들기

다시한번 View 클래스 리마인드

abstract class View<T> {
  private _element: HTMLElement | null = null;

	// 요소 컨트롤 시 사용하는 data 속성
  constructor(public data: T) {}

	// 해당 컴포넌트 요소
  element() {
    if (this._element === null) {
      throw new Error("You must call render() before accessing the element.");
    } else {
      return this._element;
    }
  }

	// 렌더링할 html 요소(템플릿 리터럴)
  abstract template(): Html;

	// 렌더링 프로세스
  render(): HTMLElement {
    const wrapEl = document.createElement('div');
    wrapEl.innerHTML = this.template().toHtml();
    this._element = wrapEl.children[0] as HTMLElement;
    this._element.classList.add(this.constructor.name);
    this.onRender();
    return this._element;
  }

	// 사용 시 override
  protected onRender() {}
}

토글할 수 있는 간단한 스위치 UI 제작

type Toggle = { on: boolean; };

class SwitchView extends View<Toggle> {
  override template() {
	  // this.data의 값에 따라 on과 off를 구분
    return html`
      <button class="${this.data.on ? 'on' : ''}">
        <span class="toggle"></span>
      </button>
    `;
  }

	// 요소에 직접 addEventListener 추가
  protected override onRender() {
    this.element().addEventListener('click', () =>
	    this.setOn(!this.data.on) // 현재 상태의 반대값
    );
  }

  setOn(bool: boolean) {
    this.data.on = bool;
    // 즉각적으로 UI에 변경사항 적용
    this.element().classList.toggle('on', bool);
  }
}

// body에 렌더링
document.querySelector('#body')!.append(
  new SwitchView({ on: false }).render()
);

타이틀과 스위치 UI를 기반으로 하나의 설정 항목을 표현하기

type Setting = {
  title: string;
  on: boolean;
};

class SettingItemView extends View<Setting> {
  switchView = new SwitchView(this.data);
	// this.data가 Setting 타입

  override template() {
    return html`
      <div>
        <span class="title">${this.data.title}</span>
        ${this.switchView}
      </div>
    `;
  }
}

// 렌더링
const setting = { title: 'Wi-Fi', on: false };

document.querySelector('#body')!.append(
  new SettingItemView(setting).render()
);

여러 개의 설정 항목을 표현하기

class SettingListView extends View<Setting[]> {
  itemViews = this.data.map(setting => new SettingItemView(setting));

  override template() {
    return html`
      <div>
        ${this.itemViews}
      </div>
    `;
  }
}

// 렌더링
const settings: Setting[] = [
  { title: 'Wi-Fi', on: false },
  { title: 'Bluetooth', on: true },
  { title: 'Sound', on: false },
];

document.querySelector('#body')!.append(
  new SettingListView(settings).render()
);