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

โดเมนของแอป

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

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

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

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

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

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

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

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

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

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

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

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

Wake Lock หน้าจอ

ไม่ควรปิดหน้าจอระหว่างการออกกำลังกาย HIIT Time จะทราบค่านี้ผ่าน Wake Lock หน้าจอ ตัวอย่างข้อมูลด้านล่างแสดงวิธีการ

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 ด้านล่าง ซึ่งจะจำลองอุปกรณ์เคลื่อนที่

ข้อความแสดงการยอมรับ

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