Áp dụng nguyên tắc lập trình ứng dụng nhỏ cho một dự án mẫu

Miền của ứng dụng

Để minh hoạ cách lập trình ứng dụng thu nhỏ được áp dụng cho một ứng dụng web, tôi cần một ý tưởng về ứng dụng nhỏ nhưng đủ hoàn chỉnh. Tập luyện ngắt quãng cường độ cao (HIIT) là một chiến lược tập luyện tim mạch, trong đó bạn sẽ tập các bài tập kỵ khí cường độ cao trong thời gian ngắn xen kẽ với các bài tập phục hồi cường độ thấp. Nhiều bài tập HIIT sử dụng bộ hẹn giờ HIIT, chẳng hạn như buổi tập trực tuyến kéo dài 30 phút này trên kênh YouTube The Body Coach TV.

Buổi tập HIIT trực tuyến với bộ hẹn giờ cường độ cao màu xanh lục.
Khoảng thời gian hoạt động.
Buổi tập luyện HIIT trực tuyến với đồng hồ hẹn giờ cường độ thấp màu đỏ.
Giai đoạn nghỉ ngơi.

Ứng dụng mẫu HIIT Time

Trong chương này, tôi đã tạo một ví dụ cơ bản về ứng dụng hẹn giờ HIIT như vậy, có tên gọi phù hợp là "HIIT Time". Ứng dụng này cho phép người dùng xác định và quản lý nhiều bộ hẹn giờ, luôn bao gồm một khoảng thời gian cường độ cao và một khoảng thời gian cường độ thấp, sau đó chọn một trong số đó cho một buổi tập luyện. Đây là một ứng dụng thích ứng có một thanh điều hướng, một thanh thẻ và 3 trang:

  • Bài tập: Trang hoạt động trong một bài tập. Ứng dụng này cho phép người dùng chọn một trong các bộ hẹn giờ và có 3 vòng tiến trình: số lượng hiệp, khoảng thời gian hoạt động và khoảng thời gian nghỉ ngơi.
  • Hẹn giờ: Quản lý các bộ hẹn giờ hiện có và cho phép người dùng tạo bộ hẹn giờ mới.
  • Lựa chọn ưu tiên: Cho phép bật/tắt hiệu ứng âm thanh và lời nói đầu ra, cũng như chọn ngôn ngữ và giao diện.

Các ảnh chụp màn hình sau đây cho thấy hình ảnh của ứng dụng.

Ứng dụng mẫu HIIT Time ở chế độ dọc.
Thẻ "Tập luyện" HIIT Time ở chế độ dọc.
Ứng dụng ví dụ HIIT Time ở chế độ ngang.
Thẻ "Tập luyện" HIIT Time ở chế độ ngang.
Ứng dụng mẫu HIIT Time cho thấy cách quản lý một bộ hẹn giờ.
Quản lý bộ hẹn giờ HIIT Time.

Cấu trúc ứng dụng

Như đã trình bày ở trên, ứng dụng này bao gồm một thanh điều hướng, một thanh thẻ và 3 trang được sắp xếp theo dạng lưới. Thanh điều hướng và thanh thẻ được nhận ra dưới dạng iframe có một vùng chứa <div> ở giữa chúng với 3 iframe khác cho các trang, trong đó có một iframe luôn hiển thị và phụ thuộc vào lựa chọn đang hoạt động trong thanh thẻ. Một iframe cuối cùng trỏ đến about:blank sẽ phân phát cho các trang được tạo động trong ứng dụng. Các trang này là cần thiết để sửa đổi bộ hẹn giờ hiện có hoặc tạo bộ hẹn giờ mới. Tôi gọi mẫu này là ứng dụng một trang có nhiều trang (MPSPA).

Chế độ xem Chrome DevTools về cấu trúc HTML của ứng dụng cho thấy ứng dụng này bao gồm 6 iframe: một cho thanh điều hướng, một cho thanh thẻ và 3 iframe được nhóm cho mỗi trang của ứng dụng, với một iframe trình giữ chỗ cuối cùng cho các trang động.
Ứng dụng này bao gồm 6 iframe.

Mã đánh dấu lit-html dựa trên thành phần

Cấu trúc của mỗi trang được nhận ra dưới dạng giàn giáo lit-html được đánh giá linh động trong thời gian chạy. Đối với nền tảng lit-html, đây là một thư viện tạo mẫu HTML hiệu quả, biểu cảm và có thể mở rộng cho JavaScript. Bằng cách sử dụng trực tiếp trong các tệp HTML, mô hình lập trình tinh thần sẽ trực tiếp hướng đến kết quả đầu ra. Là một lập trình viên, bạn viết một mẫu về giao diện của đầu ra cuối cùng, sau đó lit-html sẽ tự động điền vào các khoảng trống dựa trên dữ liệu của bạn và kết nối các trình nghe sự kiện. Ứng dụng sử dụng các phần tử tuỳ chỉnh của bên thứ ba, chẳng hạn như <sl-progress-ring> của Shoelace hoặc một phần tử tuỳ chỉnh tự triển khai có tên là <human-duration>. Vì các phần tử tuỳ chỉnh có một API khai báo (ví dụ: thuộc tính percentage của vòng tròn tiến trình), nên chúng hoạt động tốt với lit-html, như bạn có thể thấy trong danh sách bên dưới.

<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>
Ba nút và một vòng tròn tiến trình.
Phần được hiển thị của trang tương ứng với mã đánh dấu ở trên.

Mô hình lập trình

Mỗi trang có một lớp Page tương ứng, lớp này sẽ điền vào mã đánh dấu lit-html bằng cách cung cấp các phương thức triển khai của trình xử lý sự kiện và cung cấp dữ liệu cho từng trang. Lớp này cũng hỗ trợ các phương thức vòng đời như onShow(), onHide(), onLoad()onUnload(). Các trang có quyền truy cập vào một kho dữ liệu dùng để chia sẻ trạng thái toàn cục và trạng thái tùy chọn được duy trì cho mỗi trang. Tất cả các chuỗi đều được quản lý tập trung, vì vậy, quá trình quốc tế hoá được tích hợp sẵn. Về cơ bản, trình duyệt sẽ xử lý việc định tuyến miễn phí, vì tất cả những gì ứng dụng làm là chuyển đổi chế độ hiển thị iframe và đối với các trang được tạo động, hãy thay đổi thuộc tính src của iframe phần giữ chỗ. Ví dụ bên dưới cho thấy mã để đóng một trang được tạo động.

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

const page = new Page({
  eventHandlers: {
    back: (e) => {
      e.preventDefault();
      window.top.history.back();
    },
  },
});
Trang trong ứng dụng được nhận ra dưới dạng iframe.
Hoạt động điều hướng diễn ra từ iframe này sang iframe khác.

Định kiểu

Việc tạo kiểu cho các trang diễn ra theo từng trang trong tệp CSS có phạm vi riêng. Điều này có nghĩa là các phần tử thường chỉ có thể được giải quyết trực tiếp bằng tên phần tử của chúng, vì không thể xảy ra xung đột với các trang khác. Các kiểu chung được thêm vào mỗi trang, vì vậy, bạn không cần khai báo nhiều lần các chế độ cài đặt trung tâm như font-family hoặc box-sizing. Đây cũng là nơi xác định các lựa chọn về giao diện và chế độ tối. Danh sách dưới đây cho thấy các quy tắc cho trang Lựa chọn ưu tiên, trong đó trình bày các phần tử biểu mẫu trên một lưới.

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;
}
Trang lựa chọn ưu tiên của ứng dụng HIIT Time cho thấy một biểu mẫu ở bố cục dạng lưới.
Mỗi trang là một thế giới riêng. Việc tạo kiểu diễn ra trực tiếp với tên phần tử.

Khoá chế độ thức của màn hình

Trong quá trình tập luyện, màn hình không được tắt. Trên những trình duyệt hỗ trợ, HIIT Time nhận ra điều này thông qua khoá chế độ thức màn hình. Đoạn mã dưới đây cho biết cách thực hiện.

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();
    }
  });
}

Kiểm thử ứng dụng

Ứng dụng HIIT Time có trên GitHub. Bạn có thể dùng bản minh hoạ trong một cửa sổ mới hoặc ngay trong iframe được nhúng bên dưới (mô phỏng một thiết bị di động).

Lời cảm ơn

Bài viết này được Joe Medley, Kayce Basques, Milica Mihajlija, Alan Kent và Keith Gu xem xét.