Á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 nhỏ áp dụng cho một ứng dụng web, tôi cần một ý tưởng ứng dụng nhỏ nhưng đủ hoàn chỉnh. Luyện tập cường độ cao ngắt quãng (HIIT) là một chiến lược tập thể dục tim mạch, trong đó bạn luân phiên các khoảng thời gian ngắn tập thể dục không có oxy cường độ cao với các khoảng thời gian hồi phục ít cường độ hơn. Nhiều bài tập HIIT sử dụng đồng hồ HIIT, ví dụ 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 luyện HIIT trực tuyến với đồng hồ đếm thời gian cường độ cao màu xanh lục.
Thời gian hoạt động.
Buổi tập luyện HIIT trực tuyến với đồng hồ hẹn giờ màu đỏ ở cường độ thấp.
Thời gian nghỉ ngơi.

Ứng dụng mẫu Thời gian tập luyện cường độ cao ngắt quãng

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

  • Workout (Bài tập thể dục): Trang đang hoạt động trong một bài tập thể dục. Chế độ này cho phép người dùng chọn một trong các bộ hẹn giờ và có ba vòng tiến trình: số bộ, 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 các 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à đầu ra lời nói, đồng thời chọn ngôn ngữ và giao diện.

Các ảnh chụp màn hình sau đây cho thấy ấn tượng về ứng dụng.

Ứng dụng mẫu HIIT Time ở chế độ dọc.
Thẻ "Tập thể dục" trong HIIT Time ở chế độ dọc.
Ứng dụng mẫu Thời gian tập luyện cường độ cao ngắt quãng (HIIT Time) ở chế độ ngang.
Thẻ "Bài tập thể dục" trong phần Thời gian HIIT ở chế độ ngang.
Ứng dụng mẫu HIIT Time cho thấy cách quản lý đồng hồ hẹn giờ.
Quản lý bộ tính giờ thời gian HIIT.

Cấu trúc ứng dụng

Như đã nêu trên, ứng dụng này bao gồm một thanh điều hướng, một thanh thẻ và ba trang, được sắp xếp theo dạng lưới. Thanh điều hướng và thanh thẻ được nhận dạng dưới dạng iframe có vùng chứa <div> ở giữa, có thêm 3 iframe cho các trang, trong đó một iframe sẽ 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 trong ứng dụng được tạo động, 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 nhiều trang (MPSPA).

Chế độ xem Công cụ của Chrome cho nhà phát triển 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 iframe cho thanh điều hướng, một iframe cho thanh thẻ và 3 iframe được nhóm lại cho mỗi trang của ứng dụng, cùng với một iframe phần 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 hiện thực hoá dưới dạng một khung lit-html được đánh giá linh động trong thời gian chạy. Đối với nền tảng trên lit-html, đây là một thư viện tạo mẫu HTML hiệu quả, có tính biểu đạt và có thể mở rộng dành 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 đầu ra. Là một lập trình viên, bạn sẽ viết một mẫu cho kết quả 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 như <sl-progress-ring> của Dây giày 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ó API khai báo (ví dụ: thuộc tính percentage của vòng tiến trình), nên các phần tử này 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 đã 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 giúp làm sống động mã đánh dấu lit-html bằng cách cung cấp các phương thức triển khai 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 trong 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 trên mỗi trang và trạng thái toàn cục (không bắt buộc phải duy trì). Tất cả chuỗi đều được quản lý tập trung, vì vậy, tính năng quốc tế hoá được tích hợp sẵn. Về cơ bản, trình duyệt xử lý việc định tuyến miễn phí, vì tất cả những gì ứng dụng làm là bật/tắt 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 hiện dưới dạng iframe.
Điều hướng diễn ra từ iframe đến iframe.

Định kiểu

Việc định kiểu của 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 trực tiếp gọi bằng tên phần tử, vì không thể xảy ra xung đột với các trang khác. Các kiểu toàn cục được thêm vào từng trang, vì vậy, bạn không cần khai báo lại 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 giao diện và chế độ tối. Danh sách bên dưới 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 khác nhau 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 hiển thị một biểu mẫu theo bố cục lưới.
Mỗi trang là một thế giới riêng. Việc định 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 khi tập thể dục, màn hình không được tắt. Trên các trình duyệt hỗ trợ tính năng này, HIIT Time sẽ thực hiện việc này thông qua một khoá chế độ thức màn hình. Đoạn mã dưới đây cho thấy 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ể chơi với 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.