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.
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ę.
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).
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>
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();
},
},
});
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;
}
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.