הדומיין של האפליקציה
כדי להראות איך תכנות של מיני-אפליקציה מיושם באפליקציית אינטרנט, הייתי צריך רעיון לאפליקציה קטנה אבל שלמה מספיק. אימון אינטרוולים בעצימות גבוהה (HIIT) הוא אסטרטגיה של אימון קרדיו שכוללת סטים מתחלפים של תקופות קצרות של אימון אנאירובי אינטנסיבי עם תקופות התאוששות פחות אינטנסיביות. באימוני HIIT רבים נעשה שימוש בטיימרים של HIIT. לדוגמה, באימון הזה של 30 דקות אונליין בערוץ YouTube של The Body Coach TV.
אפליקציית דוגמה ל-HIIT Time
בפרק הזה בניתי דוגמה בסיסית לאפליקציית טיימר לאימוני HIIT שנקראת "HIIT Time". האפליקציה מאפשרת למשתמש להגדיר ולנהל טיימרים שונים, שכוללים תמיד אינטרוול בעצימות גבוהה ואינטרוול בעצימות נמוכה, ואז לבחור אחד מהם לאימון. זו אפליקציה רספונסיבית עם סרגל ניווט, סרגל כרטיסיות ושלושה דפים:
- אימון: הדף הפעיל במהלך אימון. המשתמש יכול לבחור אחד מהטיימרים, ויש שלושה טבעות התקדמות: מספר הסטים, התקופה הפעילה ותקופת המנוחה.
- טיימרים: ניהול של טיימרים קיימים ויצירה של טיימרים חדשים.
- העדפות: מאפשרת להפעיל או להשבית אפקטים קוליים ופלט דיבור, ולבחור שפה ועיצוב.
בצילומי המסך הבאים אפשר לראות איך האפליקציה נראית.
מבנה האפליקציה
כמו שמתואר למעלה, האפליקציה מורכבת מסרגל ניווט, מסרגל כרטיסיות ושלושה דפים, שמסודרים ברשת.
סרגל הניווט וסרגל הכרטיסיות מיושמים כמסגרות iframe עם מאגר <div> ביניהם, עם שלוש מסגרות iframe נוספות לדפים, שאחת מהן תמיד גלויה ותלויה בבחירה הפעילה בסרגל הכרטיסיות.
iframe סופי שמפנה אל about:blank משמש ליצירה דינמית של דפים בתוך האפליקציה, שנדרשים לשינוי של טיימרים קיימים או ליצירה של טיימרים חדשים.
אני קורא לתבנית הזו אפליקציית דף יחיד עם כמה דפים (MPSPA).
תגי עיצוב של lit-html מבוססי-רכיבים
המבנה של כל דף ממומש כפיגום של lit-html שעובר הערכה דינמית בזמן הריצה.
כדי להבין מה זה lit-html, מדובר בספרייה יעילה, מפורטת וניתנת להרחבה של תבניות HTML ל-JavaScript.
השימוש בו ישירות בקובצי ה-HTML הופך את מודל התכנות המנטלי לכזה שמתמקד ישירות בפלט.
כמתכנתים, אתם כותבים תבנית של הפלט הסופי, ואז lit-html ממלא את הפערים באופן דינמי על סמך הנתונים שלכם ומקשר את מאזיני האירועים.
האפליקציה משתמשת ברכיבים מותאמים אישית של צד שלישי, כמו <sl-progress-ring> של Shoelace או רכיב מותאם אישית שהוטמע באופן עצמאי בשם <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, ובדפים שנוצרו באופן דינמי לשנות את מאפיין src של ה-placeholder iframe.
בדוגמה הבאה מוצג הקוד לסגירת דף שנוצר באופן דינמי.
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;
}
חסימת מצב שינה במסך
במהלך האימון, המסך לא אמור להיכבות. בדפדפנים שתומכים בכך, 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();
}
});
}
בדיקת האפליקציה
אפליקציית HIIT Time זמינה ב-GitHub. אפשר להתנסות בהדגמה בחלון חדש, או ישירות בהטמעה של ה-iframe שבהמשך, שמדמה מכשיר נייד.
תודות
המאמר הזה נבדק על ידי ג'ו מדלי, קייסי בסקס, מיליקה מיחייליה, אלן קנט וקית' גו.