Applicazione dei principi di programmazione delle mini app a un progetto di esempio

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.

sessione online di allenamento HIIT con timer verde ad alta intensità.
. Ciclo attivo.
di Gemini Advanced.
.
. Sessione online di allenamento HIIT con timer rosso a bassa intensità.
Periodo di riposo.

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.

App di esempio HIIT Time in modalità verticale.
. HIIT Time "Allenamento" in modalità verticale.
di Gemini Advanced.
.
. App di esempio HIIT Time in modalità Orizzontale.
HIIT Time "Allenamento" in modalità Orizzontale.
di Gemini Advanced.
.
. App di esempio HIIT Time che mostra la gestione di un timer.
Gestione del timer a tempo HIIT.

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).

Visualizzazione della struttura HTML dell&#39;app in Chrome DevTools che mostra che è composta da sei iframe: uno per la barra di navigazione, uno per la barra delle schede e tre raggruppati per pagina dell&#39;app, con un iframe segnaposto finale per le pagine dinamiche.
. L'app è composta da sei iframe.

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>
Tre pulsanti e un anello di avanzamento.
Sezione della pagina visualizzata corrispondente al markup precedente.

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();
    },
  },
});
Pagina in-app realizzata come iframe.
La navigazione avviene da iframe a iframe.

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;
}
Pagina delle preferenze dell&#39;app HIIT Time che mostra un modulo in layout a griglia.
Ogni pagina è il suo mondo. Lo stile viene applicato direttamente con i nomi degli elementi.

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.