นำหลักการเขียนโปรแกรมแอปขนาดเล็กไปใช้กับโปรเจ็กต์ตัวอย่าง

โดเมนของแอป

ถ้าอยากได้วิธีเขียนโปรแกรมมินิแอปที่ใช้กับเว็บแอป ผมจึงต้องการไอเดียเล็กๆ น้อยๆ เกี่ยวกับแอปให้สมบูรณ์มากพอ การออกกำลังกายแบบ HIIT (High-intensity interval training) เป็นกลยุทธ์การออกกำลังกายแบบคาร์ดิโอที่แบ่งเป็นชุดๆ โดยสลับกันระหว่างการออกกำลังกายแบบไม่ใช้ออกซิเจนอย่างหนักเป็นระยะเวลาสั้นๆ กับช่วงพักฟื้นที่หนักน้อยกว่า การฝึกแบบ HIIT หลายครั้งจะใช้ตัวจับเวลาแบบ HIIT เช่น ในเซสชันออนไลน์ 30 นาทีนี้ จากช่อง The Body Coach TV

เซสชันการฝึก HIIT ออนไลน์ด้วยตัวจับเวลาความเข้มข้นสูงสีเขียว
ระยะเวลาที่ใช้งาน
เซสชันการฝึก HIIT ออนไลน์ที่มีตัวจับเวลาความเข้มข้นต่ำสีแดง
ระยะเวลาพัก

แอปตัวอย่าง HIIT Time

สำหรับบทนี้ เราได้สร้างตัวอย่างพื้นฐานของแอปพลิเคชันตัวจับเวลา HIIT ที่ชื่อเหมาะเจาะว่า "HIIT Time" ซึ่งช่วยให้ผู้ใช้กำหนดและจัดการตัวจับเวลาต่างๆ ซึ่งประกอบด้วยช่วงที่มีระดับความเข้มข้นสูงและต่ำเสมอ จากนั้นเลือกตัวจับเวลาใดตัวหนึ่งสำหรับเซสชันการฝึก แอปนี้เป็นแอปที่ปรับเปลี่ยนตามอุปกรณ์ที่มีแถบนําทาง แถบแท็บ และ 3 หน้า ได้แก่

  • การออกกำลังกาย: หน้าที่ใช้งานอยู่ระหว่างการออกกำลังกาย ซึ่งช่วยให้ผู้ใช้เลือกตัวจับเวลาได้ 1 รายการ และแสดงวงแหวนความคืบหน้า 3 วง ได้แก่ จํานวนชุด ระยะเวลาที่ใช้งาน และระยะเวลาพัก
  • ตัวจับเวลา: จัดการตัวจับเวลาที่มีอยู่และอนุญาตให้ผู้ใช้สร้างตัวจับเวลาใหม่
  • ค่ากำหนด: อนุญาตให้สลับเอฟเฟกต์เสียงและเอาต์พุตเสียงพูด รวมถึงการเลือกภาษาและธีม

ภาพหน้าจอต่อไปนี้แสดงถึงการแสดงผลของแอปพลิเคชัน

ตัวอย่างแอป HIIT Time ในโหมดแนวตั้ง
แท็บ "ออกกำลังกาย" ของเวลา HIIT ในโหมดแนวตั้ง
ตัวอย่างแอป HIIT Time ในโหมดแนวนอน
แท็บ "ออกกำลังกาย" ของ HIIT ในโหมดแนวนอน
ตัวอย่างแอป HIIT Time ที่แสดงการจัดการตัวจับเวลา
การจัดการตัวจับเวลา HIIT

โครงสร้างแอป

ตามที่ระบุไว้ข้างต้น แอปนี้ประกอบด้วย Navbar, แถบแท็บ และหน้า 3 หน้าจัดเรียงอยู่ในตาราง แถบนําทางและแถบแท็บจะแสดงเป็น iframe ที่มีคอนเทนเนอร์ <div> อยู่ตรงกลาง โดยมี iframe อีก 3 รายการสําหรับหน้าเว็บ โดยจะมี 1 รายการที่แสดงอยู่เสมอและขึ้นอยู่กับการเลือกที่ใช้งานอยู่ในแถบแท็บ IFrame สุดท้ายที่ชี้ไปยัง about:blank แสดงสําหรับหน้าในแอปที่สร้างแบบไดนามิก ซึ่งจําเป็นสําหรับการแก้ไขตัวจับเวลาที่มีอยู่หรือสร้างใหม่ เราเรียกรูปแบบนี้ว่าแอปหน้าเดียวแบบหลายหน้า (MPSPA)

มุมมองเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome ของโครงสร้าง HTML ของแอปที่แสดงให้เห็นว่าประกอบด้วย iframe 6 รายการ ได้แก่ iframe 1 รายการสำหรับ Navbar, 1 รายการสำหรับแถบแท็บ และ 3 รายการที่จัดกลุ่มสำหรับแต่ละหน้าของแอป โดยมี iframe ตัวยึดตำแหน่งสุดท้ายสำหรับหน้าแบบไดนามิก
แอปประกอบด้วย iframe 6 รายการ

มาร์กอัป lit-html ตามคอมโพเนนต์

โครงสร้างของแต่ละหน้าจะแสดงเป็นโครง lit-html ที่ได้รับการประเมินแบบไดนามิกเมื่อรันไทม์ ข้อมูลเบื้องต้นเกี่ยวกับ lit-html คือไลบรารีเทมเพลต HTML ที่มีประสิทธิภาพ แสดงผลได้ และขยายได้สำหรับ JavaScript การใช้รูปแบบนี้ในไฟล์ HTML โดยตรงจะทำให้รูปแบบการเขียนโปรแกรมทางจิตมุ่งเน้นที่เอาต์พุตโดยตรง ในฐานะโปรแกรมเมอร์ คุณจะเขียนเทมเพลตของลักษณะเอาต์พุตสุดท้าย จากนั้น lit-html จะเติมเต็มช่องว่างแบบไดนามิกตามข้อมูลของคุณและเชื่อมต่อกับ Listeners เหตุการณ์ แอปใช้ประโยชน์จากองค์ประกอบที่กำหนดเองของบุคคลที่สาม เช่น <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>
ปุ่ม 3 ปุ่มและวงกลมแสดงความคืบหน้า
ส่วนหน้าที่แสดงผลซึ่งสอดคล้องกับมาร์กอัปด้านบน

รูปแบบการเขียนโปรแกรม

แต่ละหน้าจะมีคลาส Page ที่สอดคล้องกันซึ่งทำให้มาร์กอัป lit-html มีชีวิตชีวาด้วยการติดตั้งใช้งานของตัวแฮนเดิลเหตุการณ์และการให้ข้อมูลสำหรับแต่ละหน้า นอกจากนี้ คลาสนี้ยังรองรับเมธอดวงจรชีวิตของออบเจ็กต์ เช่น onShow(), onHide(), onLoad() และ onUnload() หน้าเว็บมีสิทธิ์เข้าถึงที่เก็บข้อมูลที่ใช้เพื่อแชร์สถานะระดับหน้าเว็บและสถานะส่วนกลาง (ไม่บังคับ) สตริงทั้งหมดได้รับการจัดการจากส่วนกลาง จึงมีการปรับให้เป็นสากลในตัว เบราว์เซอร์จะจัดการการกำหนดเส้นทางโดยพื้นฐานแล้วโดยไม่มีค่าใช้จ่าย เนื่องจากสิ่งที่แอปทําทั้งหมดคือการสลับการแสดงผล iframe และสำหรับหน้าเว็บที่สร้างแบบไดนามิก ให้เปลี่ยนแอตทริบิวต์ src ของ iframe ตัวยึดตําแหน่ง ตัวอย่างด้านล่างแสดงโค้ดสำหรับการปิดหน้าเว็บที่สร้างขึ้นแบบไดนามิก

import Page from '../page.js';

const page = new Page({
  eventHandlers: {
    back: (e) => {
      e.preventDefault();
      window.top.history.back();
    },
  },
});
รับรู้หน้าในแอปเป็น iframe
การไปยังส่วนต่างๆ เกิดขึ้นจาก iframe หนึ่งไปยังอีก iframe หนึ่ง

การจัดรูปแบบ

การจัดรูปแบบหน้าเว็บจะเกิดขึ้นในแต่ละหน้าในไฟล์ 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 ที่แสดงแบบฟอร์มในเลย์เอาต์ตารางกริด
หน้าเว็บแต่ละหน้าเป็นโลกใบหนึ่ง การจัดสไตล์จะเกิดขึ้นกับชื่อองค์ประกอบโดยตรง

ล็อกการปลุกหน้าจอ

หน้าจอไม่ควรปิดระหว่างออกกำลังกาย ในเบราว์เซอร์ที่รองรับ ฟีเจอร์เวลา HIIT จะตรวจจับสิ่งนี้ผ่านการล็อกหน้าจอ ข้อมูลโค้ดด้านล่างแสดงวิธีดำเนินการ

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 มีให้บริการใน GitHub คุณสามารถเล่นกับเดโมในหน้าต่างใหม่ หรือใน iframe ที่ฝังไว้ด้านล่าง ซึ่งจำลองอุปกรณ์เคลื่อนที่

ขอขอบคุณ

บทความนี้ได้รับการตรวจสอบโดย Joe Medley, Kayce Basques, Milica Mihajlija, Alan Kent และ Keith Gu