應用程式網域
為了展示如何將迷你應用程式程式設計方式套用至網頁應用程式,我需要一個小型但完整的應用程式構想。高強度間歇訓練 (HIIT) 是一種有氧運動策略,透過短時間內進行高強度無氧運動,並交替進行較輕鬆的休息期。許多 HIIT 訓練都會使用 HIIT 計時器,例如 The Body Coach TV YouTube 頻道提供的這個 30 分鐘線上課程。
HIIT 時間範例應用程式
在本章中,我建立了一個基本範例,也就是一個名為「HIIT Time」的 HIIT 計時器應用程式,讓使用者定義及管理各種計時器,這些計時器一律包含高強度和低強度間隔,然後選取其中一個計時器用於訓練課程。這是一個回應式應用程式,內含一個網格選單、一個分頁選單和三個頁面:
- Workout:運動期間的有效頁面。讓使用者選取其中一個計時器,並提供三個進度環:組數數量、活動期和休息期。
- 計時器:管理現有的計時器,以及讓使用者建立新的計時器。
- 偏好設定:可讓您切換音效和語音輸出,以及選取語言和主題。
以下螢幕截圖展示了應用程式。
應用程式結構
如上所述,應用程式是由導覽列、分頁標籤列和三個頁面 (以格狀排列) 組成。
導覽列和分頁列會以 iframe 實現,並在兩者之間加入 <div>
容器,以及三個用於網頁的 iframe,其中一個 iframe 會一律顯示,並依據分頁列中的有效選取項目。最後一個指向 about:blank
的 iframe 會為動態建立的應用程式內頁面提供服務,用於修改現有計時器或建立新計時器。我稱這個模式為多頁單頁應用程式 (MPSPA)。
元件式 lit-html 標記
每個網頁的結構會以 lit-html 支架的形式實現,並在執行階段動態評估。關於 lit-html 的背景資訊,它是 JavaScript 的一種高效、具表達力且可擴充的 HTML 範本庫。直接在 HTML 檔案中使用這項功能,即可讓心智編程模式直接以輸出為導向。程式設計師會編寫範本,決定最終輸出內容的外觀,而 lit-html 會根據您的資料動態填入空白,並連結事件監聽器。應用程式會使用第三方自訂元素,例如 Shoelace 的 <sl-progress-ring>
,或是自行實作的自訂元素 <human-duration>
。由於自訂元素具有宣告式 API (例如進度環的 percentage
屬性),因此可與 lit-html 搭配使用,如下方清單所示。
<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>
程式設計模型
每個頁面都有對應的 Page
類別,您可以透過提供事件處理常式的實作方式,並為每個頁面提供資料,藉此填滿 lit-html 標記。這個類別也支援生命週期方法,例如 onShow()
、onHide()
、onLoad()
和 onUnload()
。網頁可以存取資料儲存庫,用於分享可選儲存的每個網頁狀態和全域狀態。所有字串都由中央管理,因此內建了國際化功能。瀏覽器會免費處理路由,因為應用程式只會切換 iframe 瀏覽權限,並針對動態建立的網頁變更預留位置 iframe 的 src
屬性。以下範例顯示用於關閉動態建立的頁面程式碼。
import Page from '../page.js';
const page = new Page({
eventHandlers: {
back: (e) => {
e.preventDefault();
window.top.history.back();
},
},
});
樣式
頁面樣式設定是在其限定範圍 CSS 檔案中個別頁面進行。也就是說,元素通常可以直接以元素名稱來處理,因為不會與其他頁面發生衝突。全域樣式會新增至每個網頁,因此您不必重複宣告 font-family
或 box-sizing
等主要設定。這也是定義主題和深色模式選項的地方。以下列出「偏好設定」頁面的規則,用來在格狀空間中安排各種表單元素。
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;
}
螢幕 Wake Lock
在健身期間,畫面不應關閉。在支援的瀏覽器上,HIIT Time 會透過螢幕喚醒鎖定功能實現這項功能。請參考下列程式碼片段,瞭解如何執行這項操作。
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();
}
});
}
測試應用程式
您可以在 GitHub 取得 HIIT 時間應用程式。您可以在新視窗中玩示範,也可以直接在下方的 iframe 嵌入中玩,這個 iframe 模擬了行動裝置。
特別銘謝
本文由 Joe Medley、Kayce Basques、Milica Mihajlija、Alan Kent 和 Keith Gu 共同審查。