Il dominio dell'app
Per mostrare il modo di programmare le mini app applicata a un'app web, mi serviva un'idea piccola ma abbastanza completa. Allenamento a intervalli ad alta intensità (HIIT) è una strategia di allenamento cardiovascolare che alterna serie di brevi periodi di allenamento anaerobico intenso a periodi di recupero meno intensi. Molti allenamenti HIIT utilizzano timer HIIT, ad esempio in questa sessione online di 30 minuti. del canale YouTube di The Body Coach TV.
App di esempio HIIT Time
Per questo capitolo, ho costruito un esempio di base di un'applicazione di timer HIIT dal nome appropriato "Tempo HIIT" che consente all'utente di definire e gestire vari timer, costituito sempre da un intervallo ad alta e a bassa intensità, e selezionarne uno per una sessione di formazione. È un'app reattiva con una barra di navigazione, una barra delle schede e tre pagine:
- Esercizio:la pagina attiva durante un esercizio. Consente all'utente di selezionare uno dei timer e presenta tre anelli di avanzamento: il numero di set, il ciclo attivo e il ciclo di riposo.
- Timer:consente di gestire i timer esistenti e di crearne di nuovi.
- Preferenze:consente di attivare/disattivare gli effetti sonori e l'output vocale e di selezionare la lingua e il tema.
Gli screenshot seguenti danno un'impressione dell'applicazione.
. .Struttura dell'app
Come spiegato in precedenza, l'app è composta da una barra di navigazione, una barra delle schede e tre pagine disposte in una griglia.
La barra di navigazione e la barra delle schede sono realizzate come iframe con un contenitore <div>
al centro e altri tre iframe
delle pagine, di cui una è sempre visibile e dipende dalla selezione attiva nella barra delle schede.
Viene pubblicato un iframe finale che punta a about:blank
per le pagine in-app create dinamicamente, necessarie per modificare
timer o ne creano di nuovi.
Chiamo questo pattern app a pagina singola con più pagine (MPSPA).
Markup lit-html basato su componenti
La struttura di ogni pagina è realizzata come uno scaffold lit-html
che viene valutato dinamicamente in fase di runtime.
Per una spiegazione di lit-html, è una libreria di modelli HTML efficiente, espressiva ed estensibile per JavaScript.
Utilizzandolo direttamente nei file HTML, il modello di programmazione mentale è orientato direttamente all'output.
In qualità di programmatore, scrivi un modello dell'output finale,
e lit-html colmano le lacune in modo dinamico in base ai dati e collegano i listener di eventi.
L'app utilizza elementi personalizzati di terze parti come <sl-progress-ring>
di Shoelace o un elemento personalizzato implementato autonomamente <human-duration>
.
Poiché gli elementi personalizzati hanno un'API dichiarativa (ad esempio, l'attributo percentage
dell'anello di avanzamento),
funzionano bene insieme al tag lit-html, come puoi vedere nell'elenco riportato di seguito.
<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>
Modello di programmazione
Ogni pagina ha una classe Page
corrispondente che riempie il markup lit-html con informazioni utili sulle implementazioni
dei gestori di eventi e fornendo i dati per ogni pagina.
Questo corso supporta anche metodi del ciclo di vita come onShow()
, onHide()
, onLoad()
e onUnload()
.
Le pagine hanno accesso a un datastore che serve per condividere lo stato globale per pagina e lo stato globale facoltativo.
Tutte le stringhe vengono gestite centralmente, per cui l'internazionalizzazione è integrata.
Il routing è gestito dal browser essenzialmente senza costi, poiché l'unica cosa che fa l'app è attivare/disattivare la visibilità iframe e
per le pagine create dinamicamente, modifica l'attributo src
dell'iframe segnaposto.
L'esempio seguente mostra il codice per chiudere una pagina creata dinamicamente.
import Page from '../page.js';
const page = new Page({
eventHandlers: {
back: (e) => {
e.preventDefault();
window.top.history.back();
},
},
});
Stili
Lo stile delle pagine viene applicato per pagina nel relativo file CSS con ambito.
Ciò significa che di solito gli elementi possono essere
indirizzati direttamente dai loro nomi,
poiché non si possono scontrare con altre pagine.
Gli stili globali vengono aggiunti a ogni pagina, quindi le impostazioni centrali come font-family
o box-sizing
non devono essere dichiarati ripetutamente.
Qui vengono definiti anche i temi e le opzioni della modalità Buio.
L'elenco seguente mostra le regole della pagina Preferenze che illustrano i vari elementi del modulo
su una griglia.
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;
}
Attivazione schermo
Durante un esercizio, lo schermo non deve spegnersi. Sui browser che la supportano, HIIT Time realizza questo comportamento attraverso un wakelock dello schermo. Lo snippet di seguito mostra come fare.
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();
}
});
}
Test dell'applicazione
L'applicazione HIIT Time è disponibile su GitHub. Puoi provare la demo in una nuova finestra, o direttamente nell'incorporamento dell'iframe di seguito, che simula un dispositivo mobile.
Ringraziamenti
Questo articolo è stato esaminato da Mario Rossi Kayce Basques, Milica Mihajlija, Alan Kent e Keith Gu.