Stosowanie zasad programowania miniaplikacji do przykładowego projektu

Domena aplikacji

Aby pokazać sposób programowania korzystający z miniaplikacji w aplikacji internetowej, potrzebowałem(-am) małego, ale precyzyjnego pomysłu na aplikację. Trening interwałowy HIIT Wiele treningów HIIT korzysta z liczników czasu HIIT, np. 30-minutowa sesja online z kanału The Body Coach TV w YouTube.

Sesja treningowa HIIT online z zielonym licznikiem intensywnym.
Okres aktywności.
Sesja online treningu HIIT z czerwonym licznikiem intensywnym.
Okres spoczynku.

Przykładowa aplikacja do treningu HIIT Time

Na potrzeby tego rozdziału przygotowałem podstawowy przykład aplikacji do treningu HIIT o nazwie „HIIT Time”, dzięki której użytkownik może definiować różne minutniki i nimi zarządzać. To elastyczna aplikacja z paskiem nawigacyjnym i kartami oraz 3 stronami:

  • Trening: strona aktywna podczas treningu. Pozwala użytkownikowi wybrać jeden z minutników i zawiera 3 pierścienie postępu: liczbę zestawów, okres aktywności i okres odpoczynku.
  • Minutniki: zarządza istniejącymi minutnikami i pozwala użytkownikowi tworzyć nowe.
  • Preferencje: umożliwia przełączanie efektów dźwiękowych i generowania mowy oraz wybór języka i motywu.

Na poniższych zrzutach ekranu widać aplikację.

Przykładowa aplikacja do treningu HIIT Time w trybie portretowym.
Karta „Trening” czasu HIIT w trybie portretowym.
Przykładowa aplikacja HIIT Time w trybie poziomym.
Karta „Trening” HIIT w trybie poziomym.
Przykładowa aplikacja do treningu HIIT Time, która pokazuje zarządzanie zegarkiem.
Zarządzanie licznikiem czasu HIIT.

Struktura aplikacji

Jak już wspomnieliśmy, aplikacja składa się z paska nawigacyjnego, paska kart i 3 stron ułożonych w siatkę. Pasek nawigacyjny i pasek tabulacji to elementy iframe, między którymi znajduje się kontener <div> oraz 3 dodatkowe elementy iframe dla stron, z których jeden jest zawsze widoczny i zależy od aktywnego zaznaczenia na pasku kart. Końcowy element iframe wskazujący about:blank służy do dynamicznego tworzenia stron w aplikacji, które są potrzebne do zmiany liczników czasu lub utworzenia nowych. Nazywamy to aplikacją wielostronicową opartą na wzorcu (MPSPA).

Widok w Narzędziach deweloperskich w Chrome przedstawiający strukturę HTML aplikacji z widocznym 6 elementami iframe: jednym dla paska nawigacyjnego, jednym dla paska kart i 3 zgrupowanymi elementami dla każdej strony aplikacji, z końcowym zastępczym elementem iframe dla stron dynamicznych.
Aplikacja składa się z 6 elementów iframe.

Znaczniki lit-html oparte na komponentach

Struktura każdej strony jest realizowana jako szafel lit-html, który jest oceniany dynamicznie w czasie działania. Jest to wydajna, ekspresywna i rozszerzona biblioteka szablonów HTML do wykorzystania w języku JavaScript. Dzięki użyciu go bezpośrednio w plikach HTML model programowania myślowego jest zorientowany bezpośrednio na dane wyjściowe. Jako programista piszesz szablon obrazu wynikowego, a następnie korzystasz z biblioteki lit-html, która dynamicznie wypełnia luki w wynikach wyszukiwania na podstawie Twoich danych i ułatwia odbiór detektorów zdarzeń. Aplikacja korzysta z elementów niestandardowych innych firm, takich jak <sl-progress-ring> firmy Shoelace lub samodzielnie zaimplementowanego elementu niestandardowego o nazwie <human-duration>. Elementy niestandardowe mają deklaratywny interfejs API (np. atrybut percentage pierścienia postępu), dlatego dobrze współpracują z lit-html, jak widać na liście poniżej.

<div>
  <button class="start" @click="${eventHandlers.start}" type="button">
    ${strings.START}
  </button>
  <button class="pause" @click="${eventHandlers.pause}" type="button">
    ${strings.PAUSE}
  </button>
  <button class="reset" @click="${eventHandlers.reset}" type="button">
    ${strings.RESET}
  </button>
</div>

<div class="progress-rings">
  <sl-progress-ring
    class="sets"
    percentage="${Math.floor(data.sets/data.activeTimer.sets*100)}"
  >
    <div class="progress-ring-caption">
      <span>${strings.SETS}</span>
      <span>${data.sets}</span>
    </div>
  </sl-progress-ring>
</div>
3 przyciski i pierścień postępu.
Wyrenderowana sekcja strony odpowiadająca powyższemu oznaczeniu.

Model programowania

Każda strona ma odpowiadającą mu klasę Page, która wypełnia znaczniki lit-html życiami, udostępniając implementacje modułów obsługi zdarzeń i dostarczając dane dla każdej strony. Ta klasa obsługuje też metody cyklu życia, takie jak onShow(), onHide(), onLoad() i onUnload(). Strony mają dostęp do magazynu danych, który służy do udostępniania, opcjonalnie trwałego stanu strony i stanu globalnego. Wszystkie ciągi są zarządzane centralnie, co ułatwia internacjonalizację. Routing jest obsługiwany przez przeglądarkę bezpłatnie, ponieważ aplikacja tylko przełącza widoczność elementów iframe, a w przypadku stron tworzonych dynamicznie zmienia atrybut src zastępczego elementu iframe. Przykład poniżej pokazuje kod służący do zamykania strony tworzonej dynamicznie.

import Page from '../page.js';

const page = new Page({
  eventHandlers: {
    back: (e) => {
      e.preventDefault();
      window.top.history.back();
    },
  },
});
Strona w aplikacji wyświetlana jako element iframe.
Nawigacja odbywa się z elementu iframe do elementu iframe.

Styl

Styl stron jest wprowadzany w odniesieniu do poszczególnych stron we własnym pliku CSS o zakresie. Oznacza to, że elementy można zwykle adresować bezpośrednio za pomocą ich nazw, ponieważ nie mogą występować konflikty z innymi stronami. Style globalne są dodawane do każdej strony, więc centralne ustawienia, takie jak font-family czy box-sizing, nie muszą być deklarowane wielokrotnie. Tutaj są też zdefiniowane motywy i opcje trybu ciemnego. Poniżej widać reguły dotyczące strony Ustawienia, które rozmieszczają różne elementy formularza w siatce.

main {
  max-width: 600px;
}

form {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-gap: 0.5rem;
  margin-block-end: 1rem;
}

label {
  text-align: end;
  grid-column: 1 / 2;
}

input,
select {
  grid-column: 2 / 3;
}
Strona ustawień aplikacji HIIT Time z formularzem w układzie siatki.
Każda strona to swój własny świat. Styl odbywa się bezpośrednio na podstawie nazw elementów.

Blokada wybudzania ekranu

Ekran nie powinien wyłączać się w trakcie treningu. W przeglądarkach, które go obsługują, funkcja HIIT Time korzysta z blokady wybudzania ekranu. Poniższy fragment kodu pokazuje, jak to się robi.

if ('wakeLock' in navigator) {
  const requestWakeLock = async () => {
    try {
      page.shared.wakeLock = await navigator.wakeLock.request('screen');
      page.shared.wakeLock.addEventListener('release', () => {
        // Nothing.
      });
    } catch (err) {
      console.error(`${err.name}, ${err.message}`);
    }
  };
  // Request a screen wake lock…
  await requestWakeLock();
  // …and re-request it when the page becomes visible.
  document.addEventListener('visibilitychange', async () => {
    if (
      page.shared.wakeLock !== null &&
      document.visibilityState === 'visible'
    ) {
      await requestWakeLock();
    }
  });
}

Testowanie aplikacji

Aplikacja HIIT Time jest dostępna na stronie GitHub. Możesz wypróbować wersję demonstracyjną w nowym oknie lub bezpośrednio w umieszczonym poniżej elemencie iframe, który symuluje urządzenie mobilne.

Podziękowania

Ten artykuł napisali Joe Medley, Kayce Basques, Milica Mihajlija, Alan Kent oraz Keith Gu.